Java锁的种类以及辨析(二):自旋锁的其他种类
来源:互联网 发布:淘宝 项目管理 视频 编辑:程序博客网 时间:2024/06/05 03:43
锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。
2.自旋锁的其他种类
上篇我们讲到了自旋锁,在自旋锁中 另有三种常见的锁形式:TicketLock ,CLHlock 和MCSlock
Ticket锁主要解决的是访问顺序的问题,主要的问题是在多核cpu上
public class TicketLock { private static TicketLock ticketLock = new TicketLock(); private AtomicInteger serviceNum = new AtomicInteger(); private AtomicInteger ticketNum = new AtomicInteger(); private static final ThreadLocal<Integer> LOCAL = new ThreadLocal<Integer>(); private TicketLock() {} public static TicketLock getInstance() { if (ticketLock == null) { synchronized (ticketLock) { if (ticketLock == null) { ticketLock = new TicketLock(); } } } return ticketLock; } public void lock() { int myticket = ticketNum.getAndIncrement(); LOCAL.set(myticket); while (myticket != serviceNum.get()) { } } public void unlock() { int myticket = LOCAL.get(); serviceNum.compareAndSet(myticket, myticket + 1); }}
每次都要查询一个serviceNum 服务号,影响性能(必须要到主内存读取,并阻止其他cpu修改)。
例如:
int count = 0;public void test() { new Thread(new Runnable() { @Override public void run() { TicketLock.getInstance().lock(); count = 6; while (count-- > 3) { try { Thread.sleep(1000); Log.e("test-count", "count = " + count); } catch(InterruptedException e){ e.printStackTrace(); } } TicketLock.getInstance().unlock(); } }).start(); new Thread(new Runnable() { @Override public void run() { TicketLock.getInstance().lock(); count = 1; TicketLock.getInstance().unlock(); Log.e("test-count", "count = " + count); } }).start();}打印结果:
count = 5
count = 4
count = 3
count = 1
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锁(有很多改进的地方,将自旋锁换成了阻塞锁等等)。
原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java锁的种类以及辨析(二):自旋锁的其他种类
0 0
- Java锁的种类以及辨析(二):自旋锁的其他种类
- Java锁的种类以及辨析(二):自旋锁的其他种类
- Java锁的种类以及辨析(二):自旋锁的其他种类
- Java锁的种类以及辨析(二):自旋锁的其他种类
- Java锁的种类以及辨析——自旋锁的其他种类
- java锁的种类以及辨析(一):自旋锁
- java锁的种类以及辨析(一):自旋锁
- java锁的种类以及辨析(一):自旋锁
- java锁的种类以及辨析(一):自旋锁
- java锁的种类以及辨析(一):自旋锁
- java锁的种类以及辨析——自旋锁
- Java锁的种类及辨析(一):自旋锁
- java锁的种类以及辨析
- Java锁的种类以及辨析
- java锁的种类以及辨析
- Java锁的种类以及辨析
- java锁的种类以及辨析
- java锁的种类以及辨析
- MapReduce框架分析
- 解读zookeeper的配置项
- 表格的使用及案例
- 浅析Mac OS X与Linux的启动过程
- MySQL 表级约束与列级约束
- Java锁的种类以及辨析(二):自旋锁的其他种类
- 制作html简易个人主页
- 抽牌算法
- 17年再出教育政策,利好在线教育
- WAMPSERVER开发PHPStudy环境搭建 & 第一个小程序
- js中CheckBox选择框选择选中之前的选择框
- 动态网页与静态网页区别以及各自的优缺点
- B/S技术
- Kafka三款监控工具比较