关于synchronized的问题.

此为 thinking in java 的一个例子.

如果一个线程类,在run方法里掉一个方法r(),对一个 int i 的变量做两次自加操作 , 有一个方法叫 getValue() , 取得int i的值.

main方法里,启动线程,同时一个死循环,一直取getValue();
如果getValue()取得的值是奇数则退出.

当对方法r()做 synchronized的时候,是会取得奇数的,
当且并当 getValue() 做 synchronized时,就取不到奇数了.

个人理解的 synchronized是监视器只能当前线程在执行synchronized的方法.(蹩脚的个人描述,但同网上的一个理解)

假定 A 为自增线程 ,B 为main线程.

猜测:情况 r()为 synchronized , getValue() 不为synchronized,
A自增了1次,切换到线程B,此时会取得奇数.
那么 synchronized 的方法执行时也是可以轮询到其他的线程的,这貌似也不违反并发的原则.因为另外一个线程并未执行此方法.
那为什么将 getValue() 设为 synchronized 时,就不会出现奇数的情况了呢?

帖代码:

[code="java"]

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest implements Runnable
{

private AtomicInteger ai = new AtomicInteger(0);
private Integer i = 0;

@Override
public void run()
{
    // this.ai.addAndGet(2);
    r();
}

private synchronized void r(){
    while (true)
    {
            this.i++;
            this.i++;
    }
}

public synchronized int getValue()
{
    // return ai.get();
        return i;
}

public static void main(String[] args)
{
    ExecutorService es = Executors.newCachedThreadPool();
    final AtomicIntegerTest ai = new AtomicIntegerTest();
    es.execute(ai);

    new Timer().schedule(new TimerTask()
    {
        @Override
        public void run()
        {
            System.out.println("close");
            //System.out.println(ai.getValue());
            System.exit(0);
        }
    }, 5000);

    int i;
    while (true)
    {
        i = ai.getValue();
        System.out.println("-" + i);
        if (i % 2 != 0)
        {
            System.out.println("--" + i);
            System.exit(0);
        }
        Thread.yield();
    }
}

}
[/code]

public synchronized int getValue()
private synchronized void r()

两个方法都有synchronized 修饰符,对于同一个对象,这两个方法就不能并发执行,
即每次只有一个线程调用其中的一个方法,所以就不会有奇数了

不是“根据这个情况总结出来的结论”,本来就是这种理论
关键是r()的方法是
this.i++;

this.i++;

分了两步加法,如果只是锁定r(),另一个线程就有可能在一个线程执行一次i++后调用getValue() 而取到了奇数,这个应该很好理解的,你怎么没想通呢?

同意一楼回答,这个是理论,在以前的sun的文档中有此描述,楼主细心点吧。

你是指这种情况:
public synchronized int getValue()
private void r()

我猜:
类的synchronized方法的在类实例上加锁;
类的synchronized静态方法是在类的class实例上加锁。

没看过文档,瞎猜的。