线程交互问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenbetter1996/article/details/87370478

线程中的问题

  线程交互是通过共享变量完成的,当线程之间没有交互时,开发多线程的应用程序就会变得简单很多。一旦发生了交互,很多诱发线程不安全(在多线程环境下不正确)的因素就会暴露出来。这些bug多和竞态条件、数据竞争、缓存变量有关。

1. 竞态条件

当计算的正确性取决于相对时间或者调度器所控制的多线程交叉时。就会发生竞态条件。
有以下两种类型的竞态条件。

  • check-then-act
    以下例子的“检查”是if (a == 10),“动作”是 b = a / 2
if (a == 10) {
	b = a / 2;
}

如果a和b都是局部变量自然多线程时是没有问题的。但是假设a和b是实例变量或者类静态变量。就会可能问题。比如在一条线程执行 if (a == 10) 而且成功,即将执行b = a / 2的时候,突然被调度器暂停了,然后调度器恢复了另外一条线程执行正好改变了a值。那么前一条线程恢复的时候执行 b = a / 2结果就变了。

  • read-modify-write
public int getID() {
	return count++;
}

表达式count++;是三个单独操作。

  1. 读取count的值
  2. 给count + 1
  3. 把更新值存储到count中

2. 数据竞争

竞态条件经常会和数据竞争混淆。数据竞争指的是两条或者两条以上的线程并发地访问同一块内存区域。同时其中至少一条是为了写。而且这些线程没有协调对那块区域的访问。当满足了这些条件的时候,访问顺序就是不确定的。

3. 缓存变量

为了提升性能,编译器JVM以及操作系统会协调在寄存器中或者处理器缓存中缓存变量,而不是依赖主存。每个线程都有其自己的变量拷贝。当线程写入这个变量的时候,其实是写入自己的拷贝;其他线程不太可能看到自己的变量拷贝发生变化。

猜你喜欢

转载自blog.csdn.net/chenbetter1996/article/details/87370478