【面试题精选】并发编程中可能存在的问题

13 篇文章 0 订阅

并发编程中存在的问题

在并发编程中,我们常常会遇到如下三个问题:

  1. 原子性问题
  2. 可见性问题
  3. 有序性问题

下面让我们先来了解一下这三个问题的基本概念。

1、原子性: 一个操作或者一组操作(即一段代码)要么全部执行,并且执行过程中不会被其他因素打断,要么全部不执行。

原子性的问题我们在MySQL的事务的四大特性里提到过,这里的概念跟MySQL的几乎相同。既然如此,我们就还拿常用的银行转账的实例来说明原子性的问题。
假如A有500元,B有500元,A要向B转账200元,该怎么做呢?当然要分成两步:
(1)从A的账户上扣除200元
(2)在B的账户上增加200元
但是如果A转完帐之后银行系统出现了故障,B的账户上并没有收到钱,即A的账户扣除了钱,B的账户却没有多钱。此时就出现了原子性的问题。

2、可见性: 即一个线程修修改了某个共享变量的值,那么其他线程应当能立即看到此变量被修改后的值。

举个例子,看如下代码:

// 线程1的执行体
int i = 1;
i = 2;

// 线程2的执行体
int j = i;

两个线程如果同时在不同的CPU上执行,假设线程1在CPU1上执行,线程2在CUP2上执行。因为线程是并发的,当线程1执行完语句2时,CPU1将i的值加载到高速缓存中,赋值完毕再放入高速缓存中,此时变量i的值并没有立即写入主存,即 i 的值还未改变。此时线程2执行,CPU2先读取 i 的值放入高速缓冲区,此时因为线程1的修改还未写入主存,所以变量 i 的值并未变为2,而是赋值前的1,因此此时的 j = 1。

这就是我们所说的可见性问题了,线程1修改的值没有立即让线程2看到,导致出现程序问题。

3、有序性: 即程序按照代码的先后顺序执行。

同样举个例子来说明:

int a = 1;
boolean isGood = ture;
a = 3; // 代码1
isGood = false; // 代码2

从语句上看,代码1是在代码2之前的,但是实际执行的时候,代码1一定在代码2之后么?不一定,这里会发生指令重排序。处理器为了提高程序执行的效率从而对执行语句进行优化,即不保证指令执行顺序和代码顺序相同,但是重排序有一个前提,那就是重排序后程序的运行结果要和原程序(即未进行重排序)的执行结果相同,保证程序的正确性。再看如下代码:

int a = 1;   // 语句1
int b = 5; // 语句2
b = a + 1; // 语句3
a = a + 1; // 语句4

如果JVM虚拟机对如上代码进行重排列,那么代码顺序可能的是:语句2→语句1→语句3→语句4
那有的同学可能要问了,顺序 语句2→语句1→语句4→语句3 不可以么?当然不可以,因为它违背了JVM重排序的前提。
处理机在进行指令重排序的时候要考虑到指令之间的依赖关系,如果指令1需要用到指令2的结果,那么指令2一定在指令1之前执行。

以上是单线程的情况,多线程会如何呢?看如下例子:

// 全局变量Student

//线程1
student = Student.init();  // 对Student对象进行初始化  语句1
flag = true; // 语句2

//线程2
while(flag){
	sleep();
}
addStudent(student);

线程1中的两行代码并没有依赖关系,因此他们可能会被重排列。如果 先修改flag的值为 ture 而 student 并未初始化时(语句2先执行完毕,语句1还未执行),线程2启动,则不会阻塞而直接调用 addStudent(student) 方法,但此时的 student 为空,这就导致程序出现了问题。

由此我们可以的出结论,指令重排序不会影响单个线程的执行正确性,但会影响到并发线程运行的正确性。

综上所述,我们必须同时保证程序的原子性,可见性和有序性才能保证并发程序的正确性,三者若有一个保证不了,那么程序就有可能出现错误。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值