为了模拟线程计数(锁的可重入性),写了一个简单的代码,却遇到奇怪问题。100分求助
count += m2();//不是我想当然的认为的那样,为什么?
public class Odd{
    private int count =0;
    public void m1( ){
            count++;System.out.println("1:"+get());
            int i = m2();//调用m2()
            count = count + i;
            //count += m2();//奇怪
            System.out.println("2:"+get());
            count += m2();
            System.out.println("3:"+get());
    }
    public  int m2(){
        count++;
        return -1;
    }
    public int get(){
        return count;
    }
}

解决方案 »

  1.   

    count += m2();//不是我想当然的认为的那样,为什么? count的值不变啊,我想
      

  2.   

    lz认为执行了
    count += m2();
    后count的值应该不变,是这样吗实际上
    比如,x += 10;
    就相当于 x= x+10;
    x的值当然会变这和x++不同
      

  3.   

    举个简单的例子第一个public class Test1 { /**
     * @param args
     */
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    int x = 10;
    System.out.println("x is:"+(x++));
    System.out.println("x is:"+x);
    }
    }打印结果是x is:10
    x is:11第二个例子public class Test1 { /**
     * @param args
     */
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    int x = 10;
    System.out.println("x is:"+(x+=20));
    }
    }打印结果x is:30输出的是
      

  4.   

    晕。{
      int i = m2();//调用m2() 
      count = count + i; 
    }Vs
       count += m2();//奇怪 
      

  5.   

    猜测:
    count = count + m2();执行时,
    1、以临时变量保存提取的count,并转入 m2()
    2、m2将count加1,但是不影响临时变量中的值
    3、临时变量-1并刷新count。研究字节码的朋友,证实一下。
    另外开帖加80分
      

  6.   

    /**
     * ReentrancyDemo.java:
     * 本类
     * @作者(yqj2065)
     * @版本(一个版本号或者一个日期)
     */
    public class ReentrancyDemo{
        private int count =0;//模拟,因为退出synchronized方法
        public void m1( ){
            synchronized(this){
                count++;//进入synchronized块,获得锁
                System.out.println("进入被同步块:"+get());
                {
                    int i = m2();//调用m2()
                    count = count + i;
                    //count += m2();//奇怪
                    System.out.println("退出被同步方法:"+get());
                }
                //again
                {
                    int i = m2();//调用m2()
                    count = count + i;
                    //count += m2();//奇怪
                    System.out.println("退出被同步方法:"+get());
                }
            }
            count--;
            System.out.println("退出被同步块:"+get());
        }
        public synchronized int m2(){
            count++;//进入synchronized块,获得锁
            System.out.println("进入被同步方法:"+get());
            return -1;//退出方法,
        }
        public int get(){
            return count;
        }
    }
      

  7.   

    count += m2(); 
    确实欠妥!
      

  8.   

    count += m2(); 
    执行过程如下:
     
    81: aload_0   
       82: dup
       83: getfield #2; //Field count:I  将count的值读取到栈顶,此时栈顶值是1
       86: aload_0
       87: invokevirtual #12; //Method m2:()I  调用m2(),得到结果-1保存在栈顶
       90: iadd                                相加(1+(-1)=0)
       91: putfield #2; //Field count:I  将结果存回到count再看m2()
    public int m2();
      Code:
       0: aload_0
       1: dup
       2: getfield #2; //Field count:I
       5: iconst_1
       6: iadd
       7: putfield #2; //Field count:I   将加1后的结果保存到count
       10: iconst_m1
       11: ireturn
    count += m2();
    其实就是先将左操作数的值复制出来,再准备右操作数(此过程中会修改左操作数的原值,但是不影响我们已经加载到栈里的值),执行加法,写回count。中间对count写回了两遍,不过m2()中的写回被后面一次写回覆盖掉了如果看过i=i++;类似的问题,这个应该容易理解。
      

  9.   

    这跟java计算表达式的读取规则有关。
    i=i++;的问题可以参考:
    http://blog.csdn.net/ZangXT/archive/2008/11/05/3229281.aspx
      

  10.   

    真见鬼。count=0时:count = m2() +count ;System.out.println(count); // 0
    count = count + m2();System.out.println(count); // -1和
    i=i++; vs i=++i;
    一样。
    很无聊的Java。