我知道之前已经问过“同时执行两个同步方法”的问题,并且给出的答案是“否。只有一个线程可以保存对象的锁定。然后只有那个线程可以进入同步方法在那个对象上。“ 但是,如果是真的那么请帮助我理解下面代码的输出:
public class SynchronizationMistake {
public int count;
public synchronized int getCount()
{
return count;
}
public synchronized String incrementCount()
{
count++;
return"";
}
public static void main (String args[])
{
SynchronizationMistake syn = new SynchronizationMistake();
Thread first = new Thread(syn.new readIncrementCount(syn),"First");
Thread second = new Thread(syn.new readIncrementCount(syn), "Second");
Thread third = new Thread(syn.new readIncrementCount(syn), "Third");
first.start();
second.start();
third.start();
}
private class readIncrementCount implements Runnable
{
SynchronizationMistake syn;
readIncrementCount(SynchronizationMistake syn)
{
this.syn = syn;
}
@Override
public void run() {
System.out.println("I am "+Thread.currentThread().getName()+".Count is "+ syn.getCount());
System.out.println("I am "+Thread.currentThread().getName()+".Incrementing count now"+syn.incrementCount());
System.out.println("I am "+Thread.currentThread().getName()+". After Increment Count is "+ syn.getCount());
}
}
}
Output is :
I am First.Count is 0
I am First.Incrementing count now
I am First. After Increment Count is 1
I am Third.Count is 0
I am Second.Count is 0
I am Third.Incrementing count now
I am Second.Incrementing count now
I am Third. After Increment Count is 3
I am Second. After Increment Count is 3
每次运行此程序时输出都会有所不同。我的疑问是,当第二/第三个线程得到CPU为什么它没有将'count'读为1(由第一个线程更新)?换句话说,当第一个线程锁定'syn'并将计数更新为1时,Second / Third线程是如何设置进入'getCount'method的。
答案 0 :(得分:5)
语句System.out.println("I am "+Thread.currentThread().getName()+".Count is "+ syn.getCount());
不是以原子方式执行的。部分syn.getCount()
可以在println
之前执行。这似乎也发生在你的例子中。所有线程首先执行syn.getCount()
,当时计数仍为0,然后才执行其余操作。
答案 1 :(得分:0)
你发布的这个特定执行会发生的是,所有三个线程都读取计数器的值为零,但是第一个线程有机会在其他线程之前完成所有输出,即对计数器的访问是正确同步的,但是由于输出缓冲,后期打印显示较旧的值。
尝试在第一个线程开始后进入休眠状态,这种情况应该不太可能再次发生。
答案 2 :(得分:0)
正如Henry提到的,所有线程可能首先执行syn.getCount(),然后执行syn.incrementCount。我稍微修改了你的代码来改变println语句,这样可以提供更好的图片......
public class SynchronizationMistake {
public int count;
public synchronized int getCount()
{
return count;
}
public synchronized String incrementCount() {
System.out.println("I am " + Thread.currentThread().getName() + ", incrementing the count from " + count);
count++;
System.out.println("I am " + Thread.currentThread().getName() + ", incremented the count to " + count);
return"";
}
public static void main (String args[])
{
SynchronizationMistake syn = new SynchronizationMistake();
Thread first = new Thread(syn.new readIncrementCount(syn),"First");
Thread second = new Thread(syn.new readIncrementCount(syn), "Second");
Thread third = new Thread(syn.new readIncrementCount(syn), "Third");
first.start();
second.start();
third.start();
}
private class readIncrementCount implements Runnable
{
SynchronizationMistake syn;
readIncrementCount(SynchronizationMistake syn)
{
this.syn = syn;
}
@Override
public void run() {
System.out.println("Current count is " + syn.getCount());
System.out.println(syn.incrementCount());
System.out.println("Current count is " + syn.getCount());
}
}
}
不同的输出可以如下......
输出#1:
Current count is 0
I am Second, incrementing the count from 0
Current count is 0
I am Second, incremented the count to 1
Current count is 1
I am First, incrementing the count from 1
I am First, incremented the count to 2
Current count is 2
Current count is 2
I am Third, incrementing the count from 2
I am Third, incremented the count to 3
Current count is 3
输出#2:
Current count is 0
Current count is 0
Current count is 0
I am Second, incrementing the count from 0
I am Second, incremented the count to 1
I am Third, incrementing the count from 1
I am Third, incremented the count to 2
I am First, incrementing the count from 2
I am First, incremented the count to 3
Current count is 3
Current count is 3
Current count is 3