Java自旋锁
来源:互联网 发布:win7 64位 mysql 编辑:程序博客网 时间:2024/06/05 04:48
锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。
2.自旋锁的其他种类
上篇我们讲到了自旋锁,在自旋锁中 另有三种常见的锁形式:TicketLock ,CLHlock 和MCSlock
Ticket锁主要解决的是访问顺序的问题,主要的问题是在多核cpu上
01
package
com.alipay.titan.dcc.dal.entity;
02
03
import
java.util.concurrent.atomic.AtomicInteger;
04
05
public
class
TicketLock {
06
private
AtomicInteger serviceNum =
new
AtomicInteger();
07
private
AtomicInteger ticketNum =
new
AtomicInteger();
08
private
static
final
ThreadLocal<Integer> LOCAL =
new
ThreadLocal<Integer>();
09
10
public
void
lock() {
11
int
myticket = ticketNum.getAndIncrement();
12
LOCAL.set(myticket);
13
while
(myticket != serviceNum.get()) {
14
}
15
16
}
17
18
public
void
unlock() {
19
int
myticket = LOCAL.get();
20
serviceNum.compareAndSet(myticket, myticket +
1
);
21
}
22
}
每次都要查询一个serviceNum 服务号,影响性能(必须要到主内存读取,并阻止其他cpu修改)。
CLHLock 和MCSLock 则是两种类型相似的公平锁,采用链表的形式进行排序,
01
import
java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
02
03
public
class
CLHLock {
04
public
static
class
CLHNode {
05
private
volatile
boolean
isLocked =
true
;
06
}
07
08
@SuppressWarnings
(
"unused"
)
09
private
volatile
CLHNode tail;
10
private
static
final
ThreadLocal<CLHNode> LOCAL =
new
ThreadLocal<CLHNode>();
11
private
static
final
AtomicReferenceFieldUpdater<CLHLock, CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock.
class
,
12
CLHNode.
class
,
"tail"
);
13
14
public
void
lock() {
15
CLHNode node =
new
CLHNode();
16
LOCAL.set(node);
17
CLHNode preNode = UPDATER.getAndSet(
this
, node);
18
if
(preNode !=
null
) {
19
while
(preNode.isLocked) {
20
}
21
preNode =
null
;
22
LOCAL.set(node);
23
}
24
}
25
26
public
void
unlock() {
27
CLHNode node = LOCAL.get();
28
if
(!UPDATER.compareAndSet(
this
, node,
null
)) {
29
node.isLocked =
false
;
30
}
31
node =
null
;
32
}
33
}
CLHlock是不停的查询前驱变量, 导致不适合在NUMA 架构下使用(在这种结构下,每个线程分布在不同的物理内存区域)
MCSLock则是对本地变量的节点进行循环。不存在CLHlock 的问题。
01
import
java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
02
03
public
class
MCSLock {
04
public
static
class
MCSNode {
05
volatile
MCSNode next;
06
volatile
boolean
isLocked =
true
;
07
}
08
09
private
static
final
ThreadLocal<MCSNode> NODE =
new
ThreadLocal<MCSNode>();
10
@SuppressWarnings
(
"unused"
)
11
private
volatile
MCSNode queue;
12
private
static
final
AtomicReferenceFieldUpdater<MCSLock, MCSNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(MCSLock.
class
,
13
MCSNode.
class
,
"queue"
);
14
15
public
void
lock() {
16
MCSNode currentNode =
new
MCSNode();
17
NODE.set(currentNode);
18
MCSNode preNode = UPDATER.getAndSet(
this
, currentNode);
19
if
(preNode !=
null
) {
20
preNode.next = currentNode;
21
while
(currentNode.isLocked) {
22
23
}
24
}
25
}
26
27
public
void
unlock() {
28
MCSNode currentNode = NODE.get();
29
if
(currentNode.next ==
null
) {
30
if
(UPDATER.compareAndSet(
this
, currentNode,
null
)) {
31
32
}
else
{
33
while
(currentNode.next ==
null
) {
34
}
35
}
36
}
else
{
37
currentNode.next.isLocked =
false
;
38
currentNode.next =
null
;
39
}
40
}
41
}
从代码上 看,CLH 要比 MCS 更简单,
CLH 的队列是隐式的队列,没有真实的后继结点属性。
MCS 的队列是显式的队列,有真实的后继结点属性。
JUC ReentrantLock 默认内部使用的锁 即是 CLH锁(有很多改进的地方,将自旋锁换成了阻塞锁等等)
0 0
- 自旋锁原理及java自旋锁
- 自旋锁原理及java自旋锁
- JAVA锁---------------------自旋锁
- java锁-自旋锁
- Java自旋锁
- Java自旋锁
- Java CAS自旋锁
- java 自旋锁
- Java 自旋锁
- Java自旋锁
- 【Java】CLH 自旋锁
- Java CAS自旋锁
- JAVA锁---------------------Ticket自旋锁
- 什么时候用 Java 自旋锁?
- Java中自旋锁介绍
- Java锁之自旋锁详解
- Java 中自旋锁的实现
- java虚拟机内部的自旋锁
- 记一次php开发个人微信订阅号
- POJ2366 Wireless Network(并查集)
- 凸包——Luogu1452 Beauty Contest
- 将一帧1280x1024图像保存到我的SD卡当中的方法
- 有向图的强连通分量Kosaraju算法 和 Tarjan算法思维详解及代码模板
- Java自旋锁
- memcmp拷贝函数函数
- mysql语句:SET NAMES UTF8
- 武大校赛感想
- Linux密钥登录
- Gson 用户指南
- 永不消逝的电波 -GSM空口信号的接收与解码
- Android大图绘制——硬件加速限制分析与方案
- 如何修改LINUX ROOT密码?