并发问题的源头

本文探讨并发编程中的三大问题:可见性、原子性和有序性。在多线程环境下,由于CPU缓存、线程切换和编译器优化,这些问题可能导致数据不一致和错误。通过举例分析了Java中的并发问题,如非原子操作导致的数据不一致,以及编译器优化引发的有序性问题。
摘要由CSDN通过智能技术生成

1、并发程序的问题

并发是很多问题的基础,也就是操作系统设计的基础。并发包括很多设计问题,其中有进程/线程通信、资源共享与竞争(如内存、IO设备)、进程/线程同步等。由于进程/线程的相对执行速度不可预测,它取决于其他进程/线程的活动、操作系统处理中断的方式以及操作系统的调度策略,于是就产生了以下困难:

  • 全局资源的共享存在危险。如果两个进程/线程对同一个全局变量进行读写操作,那么读写的执行顺序非常重要。
  • 操作系统的资源分配问题。两个进程互相占用了对方进程所请求的资源,那么就会产生永久地等待,即死锁。
  • 定位程序出错位置难度大。这也是由于并发程序的结果是不确定和很难复现的。

2、并发问题的源头

产生并发问题最根本的原因是CPU、内存和I/O设备之间速度的差异问题

为了平衡这几者的差异,作出了以下努力:

  • CPU增加高速缓存,平衡CPU和内存之间的速度差异;
  • 操作系统增加进程/线程,进程/线程依据时间片机制并发使用CPU资源,弥补CPU等待I/O设备的时间;
  • 编译器优化指令的执行次序,可以更高效地使用到缓存。

实际上,以上三个措施也是很多并发问题的来源。

1)可见性问题

可见性指的是一个线程对共享变量作出修改后,其他线程可以立刻看到。

在单核时代,所有线程都在一颗CPU上执行,同一时刻只有一个线程占用CPU。一个线程对缓存中的某一共享变量执行写操作后,另一个线程在被调度时,肯定可以读到前一个线程所写的变量值。因此,单核时代不存在可见性问题。

在多核时代,线程可能在不同的CPU上执行,每颗CPU都有自己的缓存。那么当多个线程在不同的CPU上执行时,这些线程会操作不同的CPU缓存。比如,线程t1操作CPU-1的缓存,线程t2操作CPU-2的缓存,当线程t1对某一共享变量执行写操作,然后写入CPU-1的缓存中,线程t2无法立刻读到CPU-1的缓存中这个变量的值,这时就出现了不可见问题。

下面以 java 为例,说明这个问题。

示例代码1:

public class Test{
   
  private long count = 0;
  
  private void add10K(){
   
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值