多线程系列(二):并发级别

接第一篇【1】

并发的级别分类:阻塞无饥饿无障碍无锁无等待


1.1 阻塞 悲观策略:保护临界区资源为第一优先级

阻塞状态下,线程需要等待其他线程释放资源,否则服务继续执行。synchronized【2】,重入锁【3】的使用会产生阻塞态线程。

1.2 无饥饿

线程按优先级高低进行调度,如果允许插队且频繁的优先级高线程插队抢占资源,就会使优先级低的线程产生饥饿(长时间得不到资源),这里使用的锁称为非公平锁【4】。公平锁【5】需要按时间先后顺序获取资源,优先级高低的属性此处无法影响资源分配。

1.3 无障碍 乐观策略

这是一种最弱的非阻塞调度。两个线程如果都是无障碍执行,临界区被占用时,不会被阻塞。如果发现数据异常,就会对之前的操作进行回滚,确保数据安全。如果没有发生数据竞争,则可以顺利经过临界区。

临界区资源存在严重冲突的情况下,会有一直回滚的行为发生的可能。如果不顺利,就会一直等待。

可行的无障碍策略:依赖“一致性标记”。操作之前,线程先读取并保持这个标记,操作完成之后,再次读取看释放别更改过,如果两者一致,说明资源访问没有冲突,如果不一致,说明资源可能在操作过程中与其他写线程冲突,需要回滚重试。并且,任何对资源有修改操作的线程,都需要在修改数据之前,更新这个一致性标记,表示数据不再安全,更新原则需要不重复,即flag   = A 先改成 B 再回改成A是不行的。

1.4 无锁【6】

无锁就是无障碍,同时保证了必然有一个线程能够在有限步内完成操作离开临界区。

可能会包含一个无限循环。循环中,线程会不断尝试修改共享变量。如果没有冲突,便是修改成功。程序退出。否则,继续尝试修改。也会有线程一直竞争失败,出现饥饿的情况。

1.5 无等待

无锁只要求线程可以在有限步骤内完成操作,无等待则需要线程必须在有限步骤内完成。步骤上限一般做限制的情况下,可以分为有界无等待和线程数无关的无等待。

无等待结构:Read-Copy-Update.

对数据的读可以不加控制。因此所有的读线程都是无等待。写数据的时候,先取得原始数据副本,接着修改副本数据,修改完后,等待合适的时机写回数据。


引用列表

【1】多线程系列(一):基本概念

【2】synchronized

【3】重入锁 

【4】非公平锁

【5】公平锁

【6】锁的优化与注意事项

你可能感兴趣的:(多线程系列(二):并发级别)