0

打印出来的结果是-20000000,证明我不需要同步size()方法。但我的理解是我也应该同步size()。这里的真实情况是什么?

public class Test {
    public static void main(String[] args){
        Counter c = new Counter();
        T1 t1 = new T1(c);
        T1 t2 = new T1(c);
        t1.start();
        t2.start();

        try{
            t1.join();
            t2.join();
        } catch (Throwable t) {

        }

        System.out.println("c=" + c.size());
    }   
}

class T1 extends Thread{
    private Counter c;

    public T1(Counter c){
        this.c = c;
    }
    public void run(){
        for(int i=0; i<10000000; i++){
            c.decrement();
        }
    }
}

class Counter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }
    public synchronized void decrement() {
        c--;
    }
    public int size() {
        return c;
    }
}
4

3 回答 3

1

It does work in your example, because after t1.join() and t2.join(), any changes made in t1 and t2 are visible to the main thread.

quoting http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.4

The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated.

T2 may accomplish this by calling T1.isAlive() or T1.join().

Basically, when a thread starts, it should see all prior changes; after a thread finishes, what it has changed should be visible to others. If thread A starts B, and thread C joins thread B

    A         B        C
    |
    w1
    |
 start B --> o
    .        |
    .        |
    .        r1       .
             w2       .
             |        .       
             |        |
             o -->  join B
                      |
                      r2
                     

It's guaranteed that r1 sees w1, r2 sees w2.

于 2013-04-13T22:38:47.373 回答
0

it will be good if you write

public int  synchronized size()
于 2013-04-13T22:37:17.487 回答
0

证明我不需要同步size()方法

实际上,它只是证明你的计数器有时可以工作。应该同步,因为基本上,它访问的字段可以同时缓存在多个寄存器中,并且没有任何迹象表明该字段在线程之间共享,多个线程可以在同一字段的纯本地副本上工作,而无需同步回到主内存。size()

运行它时看不到任何问题的事实只是证明以这种风格编写并发代码是一个坏主意。

于 2013-04-13T22:32:27.910 回答