我们知道一个线程在尝试获取锁失败后将被堵塞并增加等待队列中,它是一个如何的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列。

 在谈到CHL Node FIFO队列之前,我们先分析这样的队列的几个要素。

首先要了解的是自旋锁。所谓自旋锁即是某一线程去尝试获取某个锁时。假设该锁已经被其它线程占用的话。此线程将不断循环检查该锁是否被释放,而不是让此线程挂起或睡眠。它属于为了保证共享资源而提出的一种锁机制,与相互排斥锁类似,保证了公共资源在随意时刻最多仅仅能由一条线程获取使用。不同的是相互排斥锁在获取锁失败后将进入睡眠或堵塞状态。以下利用代码实现一个简单的自旋锁,

public class SpinLock {

private static Unsafe unsafe = null;

private static final long valueOffset;

private volatile int value = 0;

static {

try {

unsafe=getUnsafeInstance();

valueOffset = unsafe.objectFieldOffset(SpinLock.class

.getDeclaredField("value"));

} catch (Exception ex) {

throw new Error(ex);

}

}

private static Unsafe getUnsafeInstance() throws SecurityException,

NoSuchFieldException, IllegalArgumentException,

IllegalAccessException {

Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");

theUnsafeInstance.setAccessible(true);

return (Unsafe) theUnsafeInstance.get(Unsafe.class);

}

public void lock() {

for (;;) {

            int newV = value + 1;

            if (unsafe.compareAndSwapInt(this, valueOffset, 0, newV)){

            return ;

            }

        }

}

public void unlock() {

unsafe.compareAndSwapInt(this, valueOffset, 1, 0);

}

}

这是一个非常easy的自旋锁,主要看加粗加红的两个方法lock和unlock,Unsafe不过为操作提供了硬件级别的原子CAS操作,临时忽略此类,只要知道它的作用就可以,我们将在后面的“原子性怎样保证”小节中对此进行更加深入的阐述。

对于lock方法,假如有若干线程竞争,能成功通过CAS操作改动value值为newV的线程即是成功获取锁的线程。将直接通过,而其它的线程则不断在循环检測value值是否又改回0,而将value改为0的操作就是获取锁的线程运行完后对该锁进行释放,通过unlock方法释放锁,释放后若干线程又对该锁竞争。如此一来。没获取的锁也不会被挂起或堵塞,而是不断循环检查状态。图2-5-9-3可加深自旋锁的理解。五条线程轮询value变量,t1获取成功后将value置为1。此状态时其它线程无法竞争锁,t1使用完锁后将value置为0。剩下的线程继续竞争锁,以此类推。这样就保证了某个区域块的线程安全性。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3lhbmd6aGl6aG91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast"> 

图2-5-9-3 自旋锁

自旋锁适用于锁占用时间短,即锁保护临界区非常小的情景,同一时候它须要硬件级别操作。也要保证各缓存数据的一致性,另外,无法保证公平性,不保证先到先获得。可能造成线程饥饿。

在多处理器机器上,每一个线程相应的处理器都对同一个变量进行读写,而每次读写操作都将要同步每一个处理器缓存。导致系统性能严重下降。

喜欢研究java的同学能够交个朋友,以下是本人的微信号:

Java并发框架——AQS堵塞队列管理(一)——自旋锁的更多相关文章

  1. Java并发框架——AQS阻塞队列管理(三)——CLH锁改造

    在CLH锁核心思想的影响下,Java并发包的基础框架AQS以CLH锁作为基础而设计,其中主要是考虑到CLH锁更容易实现取消与超时功能.比起原来的CLH锁已经做了很大的改造,主要从两方面进行了改造:节点 ...

  2. Java并发框架——AQS阻塞队列管理(一)——自旋锁

    我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这种队 ...

  3. Java并发框架——AQS阻塞队列管理(二)——自旋锁优化

    看Craig, Landin, and Hagersten发明的CLH锁如何优化同步带来的花销,其核心思想是:通过一定手段将所有线程对某一共享变量轮询竞争转化为一个线程队列且队列中的线程各自轮询自己的 ...

  4. 深入理解Java并发框架AQS系列(一):线程

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...

  5. 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.AQS框架简介 AQS诞生于Jdk1.5,在当时低效且功能单一的synchroni ...

  6. 深入理解Java并发框架AQS系列(四):共享锁(Shared Lock)

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock) 深入 ...

  7. Java并发框架——AQS之如何使用AQS构建同步器

    AQS的设计思想是通过继承的方式提供一个模板让大家可以很容易根据不同场景实现一个富有个性化的同步器.同步器的核心是要管理一个共享状态,通过对状态的控制即可以实现不同的锁机制.AQS的设计必须考虑把复杂 ...

  8. Java并发框架——AQS之怎样使用AQS构建同步器

    AQS的设计思想是通过继承的方式提供一个模板让大家能够非常easy依据不同场景实现一个富有个性化的同步器.同步器的核心是要管理一个共享状态,通过对状态的控制即能够实现不同的锁机制. AQS的设计必须考 ...

  9. Java并发框架——AQS超时机制

    AQS框架提供的另外一个优秀机制是锁获取超时的支持,当大量线程对某一锁竞争时可能导致某些线程在很长一段时间都获取不了锁,在某些场景下可能希望如果线程在一段时间内不能成功获取锁就取消对该锁的等待以提高性 ...

随机推荐

  1. JavaScript 中的事件设计

    1. 事件绑定的几种方式  主要介绍一下 最常用的事件设计 其他就稍微带过. 直接在代码里面添加onclick指定函数名字. B) 在JS代码中通过dom元素的onclick等属性 这种做法this表 ...

  2. 解决System.Data.SQLite兼容32位和64位问题

    将当前说明文档的目录下的x64.x86目录和System.Data.SQLite.dll文件复制到您的应用程序根目录中(注意更新引用,引用System.Data.SQLite.dll即可,两目录中的不 ...

  3. onblur判断数字

    window.onload = function () { document.getElementById('text1').onblur = function () { if (isNaN(docu ...

  4. Android Studio tips and tricks 翻译学习

    Android Studio tips and tricks 翻译 这里是原文的链接. 正文: 如果你对Android Studio和IntelliJ不熟悉,本页提供了一些建议,让你可以从最常见的任务 ...

  5. php生成代金券码

    <?php/** * @param int $no_of_codes//定义一个int类型的参数 用来确定生成多少个优惠码 * @param array $exclude_codes_array ...

  6. HDU 5044 离线LCA算法

    昨天写了HDU 3966 ,本来这道题是很好解得,结果我想用离线LCA 耍一把,结果发现离线LCA 没理解透,错了好多遍,终得AC ,这题比起 HDU 3966要简单,因为他不用动态查询.但是我还是错 ...

  7. android之保存偏好设置信息到shareSharedPreferences,轻量级的保存数据的方法

    android之保存偏好设置信息到shareSharedPreferences,轻量级的保存数据的方法   SharedPreferences保存数据到xml文件 有时候要保存activity的某些状 ...

  8. 灯塔(LightHouse)

    Description As shown in the following figure, If another lighthouse is in gray area, they can beacon ...

  9. awk的接口实现方案1

    module/a.awk function sum(a, b) { return a + b } module/b.awk function sum(a, b) { return a * b } ma ...

  10. keil c51 本變數型態(Variable Type)

    本變數型態(Variable Type): 類 別 符號位元 位元組(bytes) 表 示 法 數 值 範 圍 整 數 有 2 int(short) -32768~0~>32767 4 long ...