java自旋锁
一 Test-and-Set Lock
所谓测试设置是最基本的锁,每个线程共用一把锁,进入临界区之前看没有有线程在临界区,如果没有,则进入,并上锁,如果有则等待。java实践中利用了原子的设置state变量来保证一次只有一个线程可以获得到锁。
public class TASLock implements Lock {
AtomicBoolean state = new AtomicBoolean(false); @Override
public void lock() {
while (state.getAndSet(true)) { }
}
@Override
public void unlock() {
state.set(false);
}
}
这种锁优点就是简单,缺点是在硬件层面上读取state时候,如果在cache中命中,那么直接从cache中读取就行。但是没有命中,那么将在总线产生一个广播,如果在其他处理器中的cache中找到该地址,那么就以该地址的值做为响应,并且广播该值。更糟糕的是每一个进入自旋的线程都会产生cache缺失,这样产生大量广播流量,延迟较长。
二 指数后退lock
TASLock如果产生大量自旋的线程,则效率很低,避免这个问题就是给后进入自旋的线程一个延迟避让。避让策略有很多种,这里选择指数回退。
class Backoff {
int max;
int min;
int limit;
public Backoff(int min, int max, int limit) {
this.max = max;
this.min = min;
this.limit = limit;
}
public void backoff() {
int delay = new Random().nextInt(limit);
limit = Math.min(max, 2 * limit);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class BackoffLock implements Lock{
private AtomicBoolean state = new AtomicBoolean(false); @Override
public void lock() {
Backoff backoff = new Backoff(1000, 5000, 100);
while (true) {
while (state.get()) {};
if (!state.getAndSet(true)) {
return;
} else {
backoff.backoff();
}
}
}
@Override
public void unlock() {
state.set(false);
}
}
三 基于数组的简单队列锁
上面基于TAS的lock并没有真正解决cache缺失的流量问题,所以利用java的ThreadLocal为每一个线程存储一个本地标识索引对应于是否进入临界区而不是在共享的变量上自旋,这样cache流量问题就能得到解决。
public class Alock implements Lock {
ThreadLocal<Integer> mysolitindex = new ThreadLocal<Integer>() {
protected Integer initvalue() {
return 0;
}
};
AtomicInteger tail;
boolean[] flag;
int size;
Alock (int capacity) {
size = capacity;
tail = new AtomicInteger(0);
flag = new boolean[capacity];
flag[0] = true;
}
@Override
public void lock() {
int solt = tail.getAndIncrement() % size;
mysolitindex.set(solt);
while (!flag[solt]) {};
}
}
四 改进的Alock--CLH队列锁
ALock缺点在于并发线程数量固定,空间开销比较大,每次必须分配固定数量的本地线程变量和共享变量。CLHlock解决了空间问题,它利用threadlocal保持2个指针指向pre和current来实现一个隐式的链表,并且通过pre使得cache命中率提高。
class CLHLock implements Lock {
AtomicReference<Qnode> tail;
ThreadLocal<Qnode> myNode
= new Qnode();
public void lock() {
Qnode pred
= tail.getAndSet(myNode);
while (pred.locked) {}
}}
public void unlock() {
myNode.locked.set(false);
myNode = pred;
}
}
class Qnode {
AtomicBoolean locked =
new AtomicBoolean(true);
}
本地线程中保持这指向qnode的指针mynode。如果有L个锁,n个线程,并且每个线程最多同时访问一个锁,那么需要O(L+n)空间。
java自旋锁的更多相关文章
- 自旋锁原理及java自旋锁
一.自旋锁的概念 首先是一种锁,与互斥锁相似,基本作用是用于线程(进程)之间的同步.与普通锁不同的是,一个线程A在获得普通锁后,如果再有线程B试图获取锁,那么这个线程B将会挂起(阻塞):试想下,如果两 ...
- 并发编程--CAS自旋锁
在前两篇博客中我们介绍了并发编程--volatile应用与原理和并发编程--synchronized的实现原理(二),接下来我们介绍一下CAS自旋锁相关的知识. 一.自旋锁提出的背景 由于在多处理器系 ...
- Java锁之自旋锁详解
锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) .这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类 ...
- 可重入锁 & 自旋锁 & Java里的AtomicReference和CAS操作 & Linux mutex不可重入
之前还是写过蛮多的关于锁的文章的: http://www.cnblogs.com/charlesblc/p/5994162.html <[转载]Java中的锁机制 synchronized &a ...
- Java并发框架——AQS堵塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被堵塞并增加等待队列中,它是一个如何的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这样 ...
- Java线程并发中常见的锁--自旋锁 偏向锁
随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...
- Java并发框架——AQS阻塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这种队 ...
- Java 多线程之自旋锁
一.什么是自旋锁? 自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环. 获取锁的线 ...
- Java锁的种类以及辨析(二):自旋锁的其他种类
作者:山鸡 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) .这些已经写好提供的锁为我们开发提供了便利,但是锁的具 ...
随机推荐
- 【项目1-1】使用HTML5+CSS3绘制HTML5的logo
作为一个WEB小萌新,自学了有一段时间,总是感觉停滞不前.最近反思中,想到前贤一句话:书读百遍其义自见.说到底,还是项目做的少,如果做多了,想必自然会得心应手. 利用HTML5+CSS3绘制HTML5 ...
- 推荐一个基于Vue2.0的的一款移动端开发的UI框架,特别好用。。。
一丶YDUI 一只注重审美,且性能高效的移动端&微信UI. 下面为地址自己研究去吧! 我的项目正在用,以前用的Mint-ui但是现在感觉还是这个好一点,官方给出的解释很清楚,很实用. 官方地址 ...
- Scratch2的离线下载与安装
scratch是一种程序设计语言,可以用来设计 故事.动画.游戏.音乐和美术作品. Scratch主页:https://scratch.mit.edu/ Scratch的下载与安装: 首先下载并安装A ...
- Shiro固定身份验证
Shiro基础身份验证 如果要进行shiro的日志信息读取,那么需要使用一个org.apache.shiro.util.Factory接口,在这个接口里面定义有一 取得SecuruityManager ...
- 改变图像,运用match方法判断
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>菜鸟 ...
- BOM浏览器对象模型下面几个比较实用的方法
location对象 location.href-- 返回或设置当前文档的URL location.search -- 返回URL中的查询字符串部分.例如 http://www.dreamdu.com ...
- webstrom一键上传github及使用
对于webstrom是我参加it修真园时就推荐使用的,其他编辑器我也没什么使用过.读大学的时候还是比较喜欢 Notepad++. 现在说一下webstrom主要的关键点吧! 一.实现一键上传githu ...
- JS - 讨论 - 编码习惯 - JavaScript代码到底要不要写分号?
如题:烦请大家在评论区给出原创意见!多谢!
- [Oracle]约束(constraint)
(一)约束的概念 在Oracle中,可以通过设置约束来防止无效数据进入表中.Oracle一共有5种约束: 主键约束(primary key) 外键约束(foreign key) 唯一性约束(uniqu ...
- 如何将 Microsoft Bot Framework 机器人部署以及网页应用
<Bot Framework>是微软开发的一款可让任何人制作自己的聊天机器人.该工具可以理解自然语言并对图片进行分析等,初期开放了 22 个可集成到应用的 API. 首先说到Bot大家的第 ...