我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊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(newV==1)

if (unsafe.compareAndSwapInt(this, valueOffset, 0, newV)){
                return ;
                }
        }
}
public void unlock() {
unsafe.compareAndSwapInt(this, valueOffset, 1, 0);
}
}
这是一个很简单的自旋锁,主要看加粗加红的两个方法lock和unlock,Unsafe仅仅是为操作提供了硬件级别的原子CAS操作,暂时忽略此类,只要知道它的作用即可,我们将在后面的“原子性如何保证”小节中对此进行更加深入的阐述。对于lock方法,假如有若干线程竞争,能成功通过CAS操作修改value值为newV的线程即是成功获取锁的线程,将直接通过,而其他的线程则不断在循环检测value值是否又改回0,而将value改为0的操作就是获取锁的线程执行完后对该锁进行释放,通过unlock方法释放锁,释放后若干线程又对该锁竞争。如此一来,没获取的锁也不会被挂起或阻塞,而是不断循环检查状态。图2-5-9-3可加深自旋锁的理解,五条线程轮询value变量,t1获取成功后将value置为1,此状态时其他线程无法竞争锁,t1使用完锁后将value置为0,剩下的线程继续竞争锁,以此类推。这样就保证了某个区域块的线程安全性。
 
图2-5-9-3 自旋锁

自旋锁适用于锁占用时间短,即锁保护临界区很小的情景,同时它需要硬件级别操作,也要保证各缓存数据的一致性,另外,无法保证公平性,不保证先到先获得,可能造成线程饥饿。在多处理器机器上,每个线程对应的处理器都对同一个变量进行读写,而每次读写操作都将要同步每个处理器缓存,导致系统性能严重下降。

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

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

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

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

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

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

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

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

  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并发编程:阻塞队列(转载)

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  8. 【转】Java并发编程:阻塞队列

    在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...

  9. 12、Java并发编程:阻塞队列

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

随机推荐

  1. [bzoj3673/3674可持久化并查集加强版]

    n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n,m<=2 ...

  2. 第四周小组作业:Wordcount优化

    1.小组github地址 https://github.com/muzhailong/wcPro 2.PSP表格 PSP2.1 PSP阶段 预计耗时(分钟) 实际耗时(分钟) Planning 计划 ...

  3. JAVA学习总结-多线程基础:

    参考书籍:疯狂JAVA讲义 1.进程和线程; 进程是处于运行过程中的程序;并且具有一定的独立功能;进程是系统进行系统资源分配和调度的一个独立单位. 一般而言,进程包括以下三个特征: 独立性:进程是系统 ...

  4. Java锁Synchronized对象锁和类锁区别

    java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保 ...

  5. iOS关于时间的处理

    转自:iOS关于时间的处理 做App避免不了要和时间打交道,关于时间的处理,里面有不少门道,远不是一行API调用,获取当前系统时间这么简单.我们需要了解与时间相关的各种API之间的差别,再因场景而异去 ...

  6. solr和solrcloud

    Solr = Lucene + Http(Servlet/REST) + Schema.xml+Solrconfig.xml Solr = SolrSingle + Solr MutilCore = ...

  7. [BBS]搭建开源论坛之Jforum搭配开源CKEDITOR

    本文作者:sushengmiyan 本文地址:http://blog.csdn.net/sushengmiyan/article/details/47946065 使用默认的编辑器的时候,格式都无法保 ...

  8. Linux 下的一个全新的性能测量和调式诊断工具 Systemtap,第 1 部分: kprobe

    kprobe 的原理.编程接口.局限性和使用注意事项 本系列文章详细地介绍了一个Linux下的全新的调式.诊断和性能测量工具Systemtap和它所依赖的基础kprobe以及促使开发该工具的先驱DTr ...

  9. Scala:提取器(Extractor)

    http://blog.csdn.net/pipisorry/article/details/52902671 提取器是从传递给它的对象中提取出构造该对象的参数. Scala 标准库包含了一些预定义的 ...

  10. Android Multimedia框架总结(十七)音频开发基础知识

    请尊重分享成果,转载请注明出处,本文来自逆流的鱼yuiop,原文链接:http://blog.csdn.net/hejjunlin/article/details/53078828 近年来,唱吧,全民 ...