并发的级别
-
阻塞
当一个线程持有临界资源时,其他需要获取该资源的线程将进入阻塞等待的状态,这类线程是阻塞的。
-
无饥饿
线程获取资源的优先级高低将会导致优先级别低的线程一直处于无法获取资源的状态即饥饿状态。遵循FIFO则可保证所有线程有序的获取资源
-
无障碍
无障碍代表在获取资源的策略上是乐观的,任何线程都可以去获取资源(默认认为不会发生冲突),但一但发生冲突就需要将资源进行还原操作
-
无锁
无锁即是无障碍的一种实现,利用一致性标志,通过while循环来检查数据一致性,当检测成功则代表该线程竞争成功。
-
无等待
所有线程都可以在有限步数内结束,这样不会引起饥饿现象。RCU就是无等待结构
数据访问问题
-
原子性
一个操作开始后是无法中断的,不受其他线程干扰。
-
可见性
一个线程修改了公共变量,其他线程是否能够立刻感知变量的改变
-
有序性
计算机组成中cpu在执行指令是涉及了取指、译码、执行、存储。过程中涉及不同的寄存器和计算单元,而为了提高cpu的利用率会采用流水线的模式来执行指令,但相应的寄存器或计算单元正在被占用就会导致该条指令中断,等待前面的指令释放资源。这样就会导致后面所有的指令都会慢上一个时间片。为了减少中断程序则会进行指令重排所以就会引来指令顺序性的问题。指令重排会在保证串行语义的情况下进行优化。
volatile 写操作需要在读操作之前,不然读操作是个无效操作。类似于写操作是释放‘锁’,读操作时获取‘锁’。所以对于同一把‘锁’ 需要先释放才能成功获取。假如一段指令中出现对volatile变量的写、读顺序操作,则不能将读重排到写前面。
虽然volatile保证了可见性,但并不保证原子性,类似i++这类非原子性操作,当多线程并发执行i++,还是出现回写值发生覆盖的情况,最终值始终小于预期值