线程不安全的原因

什么是原子性

我们把一段代码想象成一个房间,每个线程就是要进入这个房间的人。如果没有任何机制保证,A进入房间之后,还
没有出来;B 是不是也可以进入房间,打断 A 在房间里的隐私。这个就是不具备原子性的。
那我们应该如何解决这个问题呢?是不是只要给房间加一把锁,A 进去就把门锁上,其他人是不是就进不来了。这样
就保证了这段代码的原子性了。
有时也把这个现象叫做同步互斥,表示操作是互相排斥的。
一条 java 语句不一定是原子的,也不一定只是一条指令
比如刚才我们看到的 n++,其实是由三步操作组成的:

  1. 从内存把数据读到 CPU
  2. 进行数据更新
    比特科技3. 把数据写回到 CPU
    不保证原子性会给多线程带来什么问题
    如果一个线程正在对一个变量操作,中途其他线程插入进来了,如果这个操作被打断了,结果就可能是错误的。
    4.3.2 可见性
    主内存-工作内存
    为了提高效率,JVM在执行过程中,会尽可能的将数据在工作内存中执行,但这样会造成一个问题,共享变量在多线
    程之间不能及时看到改变,这个就是可见性问题。
    4.3.3 代码顺序性
    什么是代码重排序
    一段代码是这样的:
  3. 去前台取下 U 盘
  4. 去教室写 10 分钟作业
  5. 去前台取下快递
    如果是在单线程情况下,JVM、CPU指令集会对其进行优化,比如,按 1->3->2的方式执行,也是没问题,可以少跑
    一次前台。这种叫做指令重排序
public class ThreadDemo {
private static class Counter {
private int n1 = 0;
private int n2 = 0;
private int n3 = 0;
private int n4 = 0;
private int n5 = 0;
private int n6 = 0;
private int n7 = 0;
private int n8 = 0;
private int n9 = 0;
private int n10 = 0;
public void write() {
n1 = 1;
n2 = 2;
比特科技n3 = 3;
n4 = 4;
n5 = 5;
n6 = 6;
n7 = 7;
n8 = 8;
n9 = 9;
n10 = 10;
} p
ublic void read() {
System.out.println("n1 = " + n1);
System.out.println("n2 = " + n2);
System.out.println("n3 = " + n3);
System.out.println("n4 = " + n4);
System.out.println("n5 = " + n5);
System.out.println("n6 = " + n6);
System.out.println("n7 = " + n7);
System.out.println("n8 = " + n8);
System.out.println("n9 = " + n9);
System.out.println("n10 = " + n10);
}
} p
ublic static void main(String[] args) {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
counter.read();
}, "读");
Thread thread2 = new Thread(() -> {
counter.write();
}, "写");
thread1.start();
thread2.start();
}
}

代码重排序会给多线程带来什么问题
刚才那个例子中,单线程情况是没问题的,优化是正确的,但在多线程场景下就有问题了,什么问题呢。可能快递是
在你写作业的10分钟内被另一个线程放过来的,或者被人变过了,如果指令重排序了,代码就会是错误的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值