七、线程相关
7.1 概要
多线程导致的问题也是常见的问题,通常都是因为并发或同步导致的,为了更好的用户体验和对CPU的充分利用,并发和同步是不可或缺的编程模式。因为并发和同步难免会涉及到多线程同时访问同一个资源,或同一段内存,所以问题就从这一初衷开始衍生,常见的问题有:
1. 读脏:读脏的意思是线程访问某个内存区域里面或者某个资源的值在读的时候是一个值,在开始使用的时候又是另外一个值,这是由于可能该资源或者该内存被线程更改,总之一点就是使用某段内存或者资源的值跟该线程期望的结果不一样。读脏的问题涉及到原子性操作的概念,原子性的操作通常形容一个表达式,如果这个表达式对应的机器指令时一条指令那么就可以认为是原子性的操作,参考如下代码:
int x, y; long z; x = 3; // 原子性 z = 10; // 非原子性 y += x; // 非原子性 long local = z; // 非原子性 x++; // 非原子性 |
第一个是给x赋值,这是原子性的操作,因为这仅仅只需要一个mov指令就能完成;给z赋值,在32位CPU是不支持直接将一个值放到占8个字节的内存上,这至少需要两条mov指令;y += x,这个表达式也不是原子性,因为这个操作先获取x和y的值,然后相加,最后把结果赋给y,至少需要两条指令(add, mov);long local = z这个表达式和直接给z赋值是一样的过程;最后x++,从直观上看上去好像是原子性的操作,其实不然,因为x++的操作在编译的时候会被解释成x = x + 1,这个表达式至少需要inc