奇怪,求助

yqj2065 2009-08-14 12:59:04
为了模拟线程计数(锁的可重入性),写了一个简单的代码,却遇到奇怪问题。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;
}
}
...全文
146 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yqj2065 2009-08-14
  • 打赏
  • 举报
回复
真见鬼。count=0时:

count = m2() +count ;System.out.println(count); // 0
count = count + m2();System.out.println(count); // -1


i=i++; vs i=++i;
一样。
很无聊的Java。
zhangkailiuyu 2009-08-14
  • 打赏
  • 举报
回复
支持11楼
ZangXT 2009-08-14
  • 打赏
  • 举报
回复
这跟java计算表达式的读取规则有关。
i=i++;的问题可以参考:
http://blog.csdn.net/ZangXT/archive/2008/11/05/3229281.aspx
ZangXT 2009-08-14
  • 打赏
  • 举报
回复
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++;类似的问题,这个应该容易理解。
bacel5902 2009-08-14
  • 打赏
  • 举报
回复
count += m2();
确实欠妥!
anhy 2009-08-14
  • 打赏
  • 举报
回复
m2返回值是-1,
先加后减,所以不变
yqj2065 2009-08-14
  • 打赏
  • 举报
回复
输出:

进入被同步块:1
进入被同步方法:2
退出被同步方法:1
进入被同步方法:2
退出被同步方法:1
退出被同步块:0
yqj2065 2009-08-14
  • 打赏
  • 举报
回复
/**
* 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;
}
}
yqj2065 2009-08-14
  • 打赏
  • 举报
回复
猜测:
count = count + m2();

执行时,
1、以临时变量保存提取的count,并转入 m2()
2、m2将count加1,但是不影响临时变量中的值
3、临时变量-1并刷新count。

研究字节码的朋友,证实一下。
另外开帖加80分
泽伯 2009-08-14
  • 打赏
  • 举报
回复
为了模拟线程计数(锁的可重入性)??

楼主是如何模拟的?





yqj2065 2009-08-14
  • 打赏
  • 举报
回复
晕。

{
int i = m2();//调用m2()
count = count + i;
}

Vs
count += m2();//奇怪

lovecj6185 2009-08-14
  • 打赏
  • 举报
回复
举个简单的例子

第一个

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



输出的是
lovecj6185 2009-08-14
  • 打赏
  • 举报
回复
lz认为执行了
count += m2();
后count的值应该不变,是这样吗

实际上
比如,x += 10;
就相当于 x= x+10;
x的值当然会变

这和x++不同
yqj2065 2009-08-14
  • 打赏
  • 举报
回复
count += m2();//不是我想当然的认为的那样,为什么?

count的值不变啊,我想
lovecj6185 2009-08-14
  • 打赏
  • 举报
回复
不知道楼主想当然的认为的是什莫样啊
我们又不是你肚里的蛔虫
如何知道你想的是什莫样的呢,呵呵
anhy 2009-08-14
  • 打赏
  • 举报
回复
奇怪问题是什么问题?
难道是前自增与后自增的问题

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧