并发编程为什么会有线程安全问题

线程安全的本质:

在多线程环境下对共享变量的读写操作导致操作结果与预期结果不一致的问题。
线程安全问题都是由全局变量及静态变量引起的。

为什么会有线程安全问题呢?

  1. 多核cpu缓存导致的问题(可见性)
    多核时代,每颗 CPU 都有自己的缓存,这时 CPU 缓存与内存的数据一致性就没那么容易解决了,当多个线程在不同的 CPU 上执行时,这些线程操作的是不同的 CPU 缓存。比如下图中,线程 A 操作的是 CPU-1 上的缓存,而线程 B 操作的是 CPU-2 上的缓存,很明显,这个时候线程 A 对变量 V 的操作对于线程 B 而言就不具备可见性了
    在这里插入图片描述

  2. 操作系统的线程切换导致的问题(原子性)
    java 并发程序都是基于多线程的,自然也会涉及到任务切换,也许你想不到,任务切换竟然也是并发编程里诡异 Bug 的源头之一。任务切换的时机大多数是在时间片结束的时候,我们现在基本都使用高级语言编程,高级语言里一条语句往往需要多条 CPU 指令完成,例如这行代码count += 1,至少需要三条 CPU 指令。
    指令 1:首先,需要把变量 count 从内存加载到 CPU 的寄存器;
    指令 2:之后,在寄存器中执行 +1 操作;
    指令 3:最后,将结果写入内存(缓存机制导致可能写入的是 CPU 缓存而不是内存)。
    操作系统做任务切换,可以发生在任何一条 CPU 指令执行完,是的,是 CPU 指令,而不是高级语言里的一条语句。对于上面的三条指令来说,我们假设 count=0,如果线程 A 在指令 1 执行完后做线程切换,线程 A 和线程 B 按照下图的序列执行,那么我们会发现两个线程都执行了 count+=1 的操作,但是得到的结果不是我们期望的 2,而是 1。
    在这里插入图片描述

  3. 编译器优化导致的有序问题(有序性)
    那并发编程里还有没有其他有违直觉容易导致诡异 Bug 的技术呢?有的,就是有序性。顾名思义,有序性指的是程序按照代码的先后顺序执行。编译器为了优化性能,有时候会改变程序中语句的先后顺序,例如程序中:“a=6;b=7;”编译器优化后可能变成“b=7;a=6;”,在这个例子中,编译器调整了语句的顺序,但是不影响程序的最终结果。不过有时候编译器及解释器的优化可能导致意想不到的 Bug。

总结

本节介绍了产生线程安全问题的本质,如何解决线程安全问题呢?也就是如何保证可见性、原子性、有序性呢? 下篇文章进行介绍。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
多线程并发线程安全问题可以通过以下几种方式来解决: 1. 使用互斥锁(Mutex):互斥锁是最常用的线程同步机制,它可以确保在同一时间只有一个线程可以访问共享资源。通过在关键代码段前后加锁和解锁操作,可以防止多个线程同时访问共享资源,从而避免竞争条件。 2. 使用条件变量(Condition Variables):条件变量用于线程之间的通信和同步。它允许一个线程等待某个条件满足后再继续执行,或者通知其他线程某个条件已经满足,可以继续执行。条件变量通常与互斥锁结合使用,以确保线程在访问共享资源之前已经满足了某个特定条件。 3. 使用原子操作(Atomic Operations):原子操作是一种不可被中断的操作,可以保证在多线程环境下的数据访问的原子性。原子操作通常是由底层硬件指令或特殊的库函数实现的,可以确保在执行过程中不被其他线程干扰。 4. 使用线程安全的数据结构和库函数:一些编程语言和库提供了线程安全的数据结构和函数,它们内部实现了适当的同步机制,可以直接在多线程环境下使用,减少了手动处理线程同步的工作量。 5. 设计合理的线程调度策略:合理的线程调度策略可以避免线程之间的竞争条件和死锁等问题。例如,避免长时间的占用锁或资源,尽量减少线程之间的依赖关系,合理设置线程的优先级等。 以上是一些常用的方法和技术来解决多线程并发线程安全问题,具体的选择取决于具体的应用场景和需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qingxinziran007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值