问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

说说java锁有哪些种类,以及区别

发布网友 发布时间:2022-04-23 01:40

我来回答

1个回答

热心网友 时间:2022-05-20 20:08

锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。
1、自旋锁
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。如下

01 public class SpinLock {
02
03 private AtomicReference<Thread> sign =newAtomicReference<>();
04
05 public void lock(){
06 Thread current = Thread.currentThread();
07 while(!sign .compareAndSet(null, current)){
08 }
09 }
10
11 public void unlock (){
12 Thread current = Thread.currentThread();
13 sign .compareAndSet(current, null);
14 }
15 }
使用了CAS原子操作,lock函数将owner设置为当前线程,并且预测原来的值为空。unlock函数将owner设置为null,并且预测值为当前线程。
当有第二个线程调用lock操作时由于owner值不为空,导致循环一直被执行,直至第一个线程调用unlock函数将owner设置为null,第二个线程才能进入临界区。
由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。但当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。如果线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。
注:该例子为非公平锁,获得锁的先后顺序,不会按照进入lock的先后顺序进行。
Java锁的种类以及辨析(二):自旋锁的其他种类

锁作为并发共享数据,保证一致性的工具,在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 importjava.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 volatileCLHNode tail;
10 private static finalThreadLocal<CLHNode> LOCAL = new ThreadLocal<CLHNode>();
11 private static finalAtomicReferenceFieldUpdater<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 importjava.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 finalThreadLocal<MCSNode> NODE = new ThreadLocal<MCSNode>();
10 @SuppressWarnings("unused")
11 private volatileMCSNode queue;
12 private static finalAtomicReferenceFieldUpdater<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 }
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
光线为什么不存在 炒菜时要等到油冒烟吗 高考数学选修没涂有分吗? 高考选修不涂有分数吗 《宫》中插曲是什么乐器演奏的? 电视剧《宫》的主题曲和片尾曲分别是什么? 爱我的人和我爱的人原唱是裘海正还是游鸿明 刑法对追诉时效的规定 刑事案件追诉期限的法律规定是什么? 爱奇艺海外版怎么下载 java 对象锁和方法锁有什么区别 如何使用java的锁机制 java中的锁有哪几种 java中的lock锁,多次获得,只unlock一次,会有什么效果 Java中有哪些锁,区别是什么 JAVA锁有哪些种类,以及区别 唯品会月度账单可以删除吗? 小龙虾和普通的虾有何区别?一共有哪些虾?常见的可养殖虾品种有哪些? 龙虾是海虾吗? 小龙虾是虾吗?它的学名是什么? 大龙虾和普通大虾吃起来口感味道 有啥不同? 泰医简述体内的糖、脂肪和蛋白质(氨基酸)三者在代谢上的相互关系 龙虾是龙还是虾? 苏氨酸是生糖氨基酸,还是生糖兼生酮氨基酸? 大虾是龙虾吗 龙虾和虾有什么区别? 下述氨基酸除哪种外,都是生糖氨基酸或生糖兼生酮氨基酸?? 龙虾和对虾一个概念吗 丙氨酸可以转化为丙酮酸,为什么不是生酮氨基酸 龙虾是属于虾类吗? Java锁的几种应用 经常会听到Java锁这个词,但给自己的感觉很朦胧,有办法清楚的了解它吗?大虾们给个建议!!! java 多线程什么是锁 Java的锁机制有什么用 java中共享锁与无锁的区别? java为什么要对对象加锁 java中文件加锁机制是怎么实现的。 Java多线程中,锁是什么,所谓的获取锁是什么意思 JAVA多线程中“锁”的概念的理解 JAVA锁机制 有小例子说明最好! java锁的可见性的是怎么保证的 java中如何锁住一个文件不让其他程序修改 wps怎么把文本转换成表格 怎样把wps文字转换成wps表格? 怎么把手机wpsword转换为Excel文档? 香椿用开水烫过后可以保存多久?怎么保存? 香椿的如何保存一年四季都可以吃到? 香椿如何保存? 香椿可以冷冻保存吗? 怎么保存新鲜的香椿?