public class AtomicityTest implements Runnable {

private int i = 0;
public int getValue() { return i;}
private synchronized void evenIncrement() { i++; i++;}
@Override
public void run() {
while(true)
evenIncrement();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
while(true){
int val = at.getValue();
if(val % 2 != 0){
System.out.println(val);
System.exit(0);
}
}
}                         
}
这道程序不理解。
为什么会输出val的值,是不是可以这样理解:当一个线程加1后,还没来得及两次加1,这时有一个线程进来getvalue,所以输出了值?
但为什么把getvalue加个synchronized后,就不会输出值了?
我感觉getvalue也加锁后,只能保证一个线程使用getvalue,但似乎没有任何代码可以保证操作evenIncrement与getvalue的线程是同一个线程,这是为什么呢?多线程

解决方案 »

  1.   

    为什么会输出val的值,是不是可以这样理解:当一个线程加1后,还没来得及两次加1,这时有一个线程进来getvalue,所以输出了值?
    这里我同意。可以在evenIncrement()加上输出语句试试看
    但为什么把getvalue加个synchronized后,就不会输出值了?
    因为这里的synchronized是对象锁,锁的对象是this。一旦对象里的某个方法上了锁,那么其他所有方法也都上了锁。
    程序进入private synchronized void evenIncrement() { i++; i++;}因为上了锁,所以getValue()%2必定==0,当然
    if(val % 2 != 0){
    System.out.println(val);
    System.exit(0);
    }
    这句话就永远走不到了
      

  2.   

    一旦对象里的某个方法上了锁,那么其他所有方法也都上了锁。
    我没说清楚,应该是一旦对象里的某个synchronized方法上了锁,那么其他所有synchronized方法也都上了锁。
      

  3.   

    应该是一旦对象里的某个synchronized方法上了锁,那么其他所有synchronized方法也都上了锁?
    还是不明白?
    不知道你要表达什么意思?
    synchronized就是锁,什么叫某个synchronized方法上了锁?
    而且按照你的说法,那第一次用synchronized给evenIncrement上锁后,其他也都上了锁,但为什么还会输出呢?
      

  4.   


    当多个线程使用同一个synchronized锁时(例子中这把锁是 AtomicityTest 的实例 at),所有被 synchronized{} 块包裹的代码可以认为是在一个“单线程”中执行的。“但似乎没有任何代码可以保证操作evenIncrement与getvalue的线程是同一个线程”事实上因为这两个方法被同一把锁保护,不管有多少线程想要运行它们,都得排成一队,所以可以看作它们被一个虚拟的 “单线程” 拘禁。
      

  5.   

    private synchronized void evenIncrement()
    {
       函数体
    }
    的实现其实是
    private void evenIncrement()
    {
        synchronized(this)
        {
            函数体
        }
    }
    锁其实就是锁的自己的实例
      

  6.   

    对象锁啥意思呢,比方说 class AtomicityTest 
    里边有个private synchronized void evenIncrement() { i++; i++;},这叫做给方法上锁
    其实这方法等于是这样的写法
    private void evenIncrement() {
      synchronized(this){
        i++;i++;
      }
    }这里的synchronzed是给代码块上锁。
    this就是锁。
    给方法上锁,锁默认都是this。
    也就是给方法上锁的写法,都公用一把对象锁this
    所以你给getValue()方法上锁,其实是和 evenIncrement()公用一把锁。
    你也可以试一试把this换成别的任何东西,保证方法间的锁不一样,这样方法间就不会出现同步问题了。