类有2个同步方法..当一个线程在第二个方法里面时,另一个线程可以进入第一个方法吗?

时间:2014-10-18 06:21:15

标签: java multithreading

我知道之前已经问过“同时执行两个同步方法”的问题,并且给出的答案是“否。只有一个线程可以保存对象的锁定。然后只有那个线程可以进入同步方法在那个对象上。“ 但是,如果是真的那么请帮助我理解下面代码的输出:

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的。

3 个答案:

答案 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