多线程引发数据不一致字节码层面理解

多线程引发数据不一致字节码层面理解

先看一段代码

public class TestSynchronized {

    static int count;
    static Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    count++;
                }
            }
        };

        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                for (int i = 0; i < 5000; i++) {
                    count--;
                }
            }
        };

        t1.start();
        t2.start();

        Thread.currentThread().sleep(1000);
        System.out.println(count);
    }


}

这里使用匿名内部类的方式创建两线程,并发修改TestSynchronized.count静态变量
在这里插入图片描述
编译出的字节码文件如上

TestSynchronized.class main方法的字节码指令为:
在这里插入图片描述
上述指令的的意思是先new 一个TestSynchronized$1对象(也就是匿名内部类对象)压入操作数栈中,复制一份并压入栈,将常量池中指向字符串"t1"的引用压入栈,调用TestSynchronized$1的init方法(弹出栈顶的TestSynchronized$1对象和"t1"),然后将创建的对象存入局部变量表索引为1的位置,之后以同样的方式创建TestSynchronized$2,然后分别调用他们的start方法,最后输出TestSynchronized.count。

重点在TestSynchronized$1 run方法的指令中
在这里插入图片描述0行操作:将常量0压入栈
1:弹出栈存到局部变量表索引为1的位置(也就是给i赋值)
2:将表索引为1位置的值压入操作数栈
3:将1000压入栈
6:栈顶两数比较(即1与1000比较,1>1000的话跳转23行,否则继续执行)
9:获取TestSynchronized的静态变量count,并压入栈
12:将常量1压入栈
13:栈顶两数相加,并把结果压入栈
14:将栈顶元素赋给TestSynchronized的静态变量count
17:表中索引为1位置的值自增1
20:跳转到2

由上述指令可看出在9行中是获取TestSynchronized的count,14行将操作完的结果赋回给count。
就可能出现这种情况:假设当前count=1,线程1执行到了第9行获取了count的值1,但时间片结束,线程2获取时间片也执行到了第9行获取了count的值1,然后继续执行将操作完的值0赋给count,此时count的值为0,但线程1中操作数栈的值还是1,继续执行也将操作完的结果2赋给count。此时count的值为2,这样就发生了明明对count做了加一和减一操作,但值却变为了2。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值