@SuppressWarnings("all")public class demo1{static Integer c=0;public static void main(String[] args) throws InterruptedException {Thread a=new Thread(){@Overridepublic void run() {synchronized (c) {for (int i = 0; i < 10000; i++) {c++;} }}}; Thread b=new Thread(){@Overridepublic void run() {synchronized (c) {for (int i = 0; i < 10000; i++) {c--;}}}}; a.start();b.start();a.join();b.join();System.out.println(c);} }这是上述代码,按理说a b线程开始启动后,对同一个对象c进行处理,在处理并发的情况下,我用同步代码进行同步,使线程获取c对象才执行代码,按理来说应该c值应该不变。但是测试 结果有偏差,而且很大,说明还是很并发的。 请各位大佬指点迷津。
2 回答
慕沐林林
TA贡献2016条经验 获得超9个赞
若使对象加锁,则需要声明显式对象(即显示使用new),内存地址是确定的:
static Integer c = new Integer(0);
若使用autoboxing, 则会有不可预测的效果,因为上述代码中在更变c变量的内存地址,使得锁不再锁定同一对象。
1. 从 javap -c解析的结果可以看到 Integer c = 0 编译器使用java/lang/Integer.valueOf方法替换,再看看valueOf中有IntegerCache,当数据超过127时则使用new Integer(i);
2. 我们再看看简单的Integer x = 0; x ++; 则会:
以上可知x++仍然会使用valueOf方法,所以锁的对象一直变更导致同步效果失效。
注:请注意代码风格,养成良好习惯
慕盖茨4494581
TA贡献1850条经验 获得超11个赞
static Integer c = 0;
/**
* @param args
*/
public static void main(String[] args) {
Integer tmp = c;
System.out.println(tmp == c);//true
Integer tmp2 = c++;
System.out.println(tmp2 == c);//false
}
- 2 回答
- 0 关注
- 542 浏览
添加回答
举报
0/150
提交
取消