2

我正在尝试设置同步方法和非同步方法之间的区别..我尝试了以下代码

 class Counter {
    private int counter = 10;
    public int getCounter() {
        return counter;
    }

    public synchronized void doIncrementAndDecrement() {
        counter++;
        keepBusy(500);
        counter--;
    }

    public void keepBusy(int howLong) { // (D)
        long curr = System.currentTimeMillis();
        while (System.currentTimeMillis() < curr + howLong)
            ;
    }
}

class MyCounterThread extends Thread {

    Counter c;

    public MyCounterThread(Counter c, String name) {
        // TODO Auto-generated constructor stub
        super(name);
        this.c = c;
        start();
    }

    @Override
    public void run() {
        for (;;) {
            c.doIncrementAndDecrement();
            sleepForSometime();
            System.out.println(c.getCounter());
        }
    }

    public void sleepForSometime() { // (D)
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class UnSynchronizedExapmle {

    public static void main(String[] args) throws InterruptedException {
        Counter c = new Counter();
        MyCounterThread t1 = new MyCounterThread(c, "A");
        MyCounterThread t2 = new MyCounterThread(c, "B");
        MyCounterThread t3 = new MyCounterThread(c, "C");
    }
}

所以上面我有doIncrementAndDecrement()同步方法..

所以我希望计数器的值每次都应该是 10。但这不会发生我的输出就像

10
10
11
10
10
10
10
11
10
10
11
10
11
11
10
10
11
10
11
10
10
10
11
10
10
11
10

所以请帮助我为什么会发生这种情况..或者任何解释同步和异步方法之间区别的博客/文章

4

3 回答 3

5

您的 getCounter() 方法未同步。因此,即使一个线程可能会锁定该方法,另一个线程仍然可以访问并打印您的计数器变量

于 2012-05-17T07:26:28.333 回答
2

您的代码没有同步getCounter方法,以便System.out.println可以输出计数器的内部状态。synchronized on 方法与synchronized(this)相同。

于 2012-05-17T07:27:31.033 回答
1

...如果我在我的 keepBusy() 方法中编写 Thread.sleep() 会有什么不同.. 因为两种情况下的输出都完全不同。

它的作用是使keepBusy()花费很长时间,因此它使getCounter()等待很长时间。

输出的差异是由于同步导致无法getCounter()“看到”处于递增状态的计数器。

我的意思是,在线程调度或锁定方面,Thread.sleep() 和上述 while 循环在 keepBusy() 方法中有何不同。

没有什么不同的。


作为记录,对于一个真正的程序来说,让一个像keepBusy()这样的方法在同步方法或块中休眠是个坏主意。这sleep会导致任何其他尝试在目标对象上同步的线程被阻塞......这可能会降低应用程序的实际并行度。

于 2012-05-17T08:09:01.293 回答