java线程使用对象锁的概念来保证在线程操作过程中避免其他线程的干扰,但下面的几个例子经实际运行后,运行结果竟然一样?请各位对此感兴趣的大虾探讨一下:
程序源码如下:
public class ThreadExample {
private int j;
public static void main(String args[]) {
Num num = new Num(100);
Inc inc = new Inc(num);
Dec dec = new Dec(num);
for (int i = 0; i < 2; i++) {
Thread t = new Thread(inc);
t.start();
t = new Thread(dec);
t.start();
}
}
}class Num {
private int j;
public Num(int kk) {
j = kk;
} public void inc() {   //B.
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
} public void dec() {   //B.
j--;
System.out.println(Thread.currentThread().getName() + "-dec:" + j);
}}class Inc implements Runnable {
private Num num;
public Inc(Num num) {   
this.num = num;
} public void run() {     //A.
for (int i = 0; i < 10; i++) {
num.inc();
}
}
}class Dec implements Runnable {
private Num num;
public Dec(Num num) {
this.num = num;
} public void run() {   //A.
for (int i = 0; i < 10; i++) {
num.dec();
}
}
}
现在分几种情况运行上面的例子:
1、不做任何修改,直接运行;
2、将A处的两个方法都用synchronized修饰,同步后运行;
3、将B处的两个方法都用synchronized修饰,同步后运行;
4、将A、B处的四个方法都用synchronized修饰,同步后运行;
本来以为它们的运行结果不会都一样,可运行结果显示竟然都向下面一样:执行结果:
Thread-0-inc:101
Thread-0-inc:102
Thread-0-inc:103
Thread-0-inc:104
Thread-0-inc:105
Thread-0-inc:106
Thread-0-inc:107
Thread-0-inc:108
Thread-0-inc:109
Thread-0-inc:110Thread-1-dec:109
Thread-1-dec:108
Thread-1-dec:107
Thread-1-dec:106
Thread-1-dec:105
Thread-1-dec:104
Thread-1-dec:103
Thread-1-dec:102
Thread-1-dec:101
Thread-1-dec:100Thread-2-inc:101
Thread-2-inc:102
Thread-2-inc:103
Thread-2-inc:104
Thread-2-inc:105
Thread-2-inc:106
Thread-2-inc:107
Thread-2-inc:108
Thread-2-inc:109Thread-3-dec:108Thread-2-inc:109Thread-3-dec:108
Thread-3-dec:107
Thread-3-dec:106
Thread-3-dec:105
Thread-3-dec:104
Thread-3-dec:103
Thread-3-dec:102
Thread-3-dec:101
Thread-3-dec:100
(注:中间的空白行是为了看起来清楚,人为添加!)难道synchronized同步方法不起作用?

解决方案 »

  1.   

    Thread t = new Thread(inc);
    t.start();
    t = new Thread(dec);
    t.start();这段代码中好像同步的是两个不同的对象,不知道是不是这样???学习中!!!
      

  2.   

    把Dec类改为包含在Inc类中的一个synchronized方法,应该就可以了,试试???
      

  3.   

    诸位大虾还是没有把这个例子看清楚,我并不是要求它的最后结果是100,而是说:我们贯常理解的synchronized方法,应该是作为一个不间断的过程执行,但结果却似乎与此无关,我们想要搞清楚JVM对于synchronized方法的执行机制是什么?
      

  4.   

    楼主对synchronized的理解不够清晰啊,加了synchronized之后出现这样的输出是合法的我稍微解释一下:
    synchronized 加在A处,表示 同一Dec对象的run(方法)不能同时被两个线程进入, 同样 同一Inc对象的run(方法)不能同时被两个线程进入. 而实际上这段程序中一个线程用了一个Dec对象,另一个线程用了一个Inc对象. synchronized 所加的锁体现不出任何效果
      

  5.   

    synchronized 加在B处, 表示同一Num对象的inc()方法不能同时被两个线程进入, 同一Num对象的dec()方法不能同时被两个线程进入, 但两个线程可以同时一个进入这个Num对象的inc()方法,另一个进入这个Num对象的dec()方法.这段程序Num对象只有一个,所以原理上锁应该起作用.
    但执行的输出结果看不出锁是否起到作用,Thread-0和Thread-2应该没有同时进入inc(),即使输出上有
    Thread-0-inc:107
    Thread-2-inc:108
    Thread-0-inc:109
    这样混杂情况,也可能是Thread-0和Thread-2应该没有同时到达inc(),其中Thread-2被挂起,等待Thread-0出了inc()之后再进去的,所以这些输出都是合法的.
      

  6.   

    如果楼主要问为什么输出是这个次序(而不是其他的合法次序),那我只能说这和Java虚拟机底层实现的调度策略有关了,呵呵
      

  7.   

    其实,还有些内容需要考虑:synchronized通过给线程范围内的对象加锁而避免其他线程对它的"非法"改变,而我们一向认为:加锁的时间应该就是synchronized方法或程序块的执行时间.基于此,我们可以认为:同步方法的执行过程中,其握有锁的对象的状态应该是不受其他外部线程的"非法"改变的,结合到我们这个例子,我们可以认为:某一个线程的输出(无论是执行增加的线程还是执行减少的线程)应该是连续的,不受"打扰的",而这个例子却打破了这个悖论!我们把这个例子提出来,目的就是为了搞清楚这一点.不知楼上的是否认同?