可重入锁和不可重入锁
转自https://www.cnblogs.com/dj3839/p/6580765.html
锁的简单应用
用lock来保证原子性(this.count++这段代码称为临界区)
什么是原子性,就是不可分,从头执行到尾,不能被其他线程同时执行。
可通过CAS来实现原子操作
CAS(Compare and Swap):
CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。
CAS主要通过compareAndSwapXXX()方法来实现,而这个方法的实现需要涉及底层的unsafe类
unsafe类:java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作
这里有个介绍原子操作的博客
https://my.oschina.net/xinxingegeya/blog/499223
还有对unsafe类详解的博客
http://www.cnblogs.com/mickole/articles/3757278.html
1 public class Counter{2 private Lock lock = new Lock();3 private int count = 0;4 public int inc(){5 lock.lock();6 this.count++;7 lock.unlock();8 return count;9 } 10 }
不可重入锁
先来设计一种锁
1 public class Lock{2 private boolean isLocked = false;3 public synchronized void lock() throws InterruptedException{4 while(isLocked){ 5 wait();6 }7 isLocked = true;8 }9 public synchronized void unlock(){ 10 isLocked = false; 11 notify(); 12 } 13 }
这其实是个不可重入锁,举个例子
1 public class Count{2 Lock lock = new Lock();3 public void print(){4 lock.lock();5 doAdd();6 lock.unlock();7 }8 public void doAdd(){9 lock.lock(); 10 //do something 11 lock.unlock(); 12 } 13 }
当调用print()方法时,获得了锁,这时就无法再调用doAdd()方法,这时必须先释放锁才能调用,所以称这种锁为不可重入锁,也叫自旋锁。
可重入锁
设计如下:
1 public class Lock{2 boolean isLocked = false;3 Thread lockedBy = null;4 int lockedCount = 0;5 public synchronized void lock()6 throws InterruptedException{7 Thread thread = Thread.currentThread();8 while(isLocked && lockedBy != thread){9 wait(); 10 } 11 isLocked = true; 12 lockedCount++; 13 lockedBy = thread; 14 } 15 public synchronized void unlock(){ 16 if(Thread.currentThread() == this.lockedBy){ 17 lockedCount--; 18 if(lockedCount == 0){ 19 isLocked = false; 20 notify(); 21 } 22 } 23 } 24 }
相对来说,可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。
第一个线程执行print()方法,得到了锁,使lockedBy等于当前线程,也就是说,执行的这个方法的线程获得了这个锁,执行add()方法时,同样要先获得锁,因不满足while循环的条件,也就是不等待,继续进行,将此时的lockedCount变量,也就是当前获得锁的数量加一,当释放了所有的锁,才执行notify()。如果在执行这个方法时,有第二个线程想要执行这个方法,因为lockedBy不等于第二个线程,导致这个线程进入了循环,也就是等待,不断执行wait()方法。只有当第一个线程释放了所有的锁,执行了notify()方法,第二个线程才得以跳出循环,继续执行。
这就是可重入锁的特点。
java中常用的可重入锁
synchronized
java.util.concurrent.locks.ReentrantLock
ps:顺便记录下java中实现原子操作的类(记录至http://blog.csdn.net/huzhigenlaohu/article/details/51646455)
- AtomicIntegerFieldUpdater:原子更新整型的字段的更新器
- AtomicLongFieldUpdater:原子更新长整型字段的更新器
- AtomicStampedReference:原子更新带有版本号的引用类型。该类将整型数值与引用关联起来,可用于原子的更新数据和数据的版本号,可以解决使用CAS进行原子更新时可能出现的ABA问题。
- AtomicReference :原子更新引用类型
- AtomicReferenceFieldUpdater :原子更新引用类型里的字段
- AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子更新一个布尔类型的标记位和应用类型
- AtomicIntegerArray :原子更新整型数组里的元素
- AtomicLongArray :原子更新长整型数组里的元素
- AtomicReferenceArray : 原子更新引用类型数组的元素
- AtomicBooleanArray :原子更新布尔类型数组的元素
- AtomicBoolean :原子更新布尔类型
- AtomicInteger: 原子更新整型
- AtomicLong: 原子更新长整型
转载于:https://www.cnblogs.com/ffaiss/p/11132984.html
可重入锁和不可重入锁相关推荐
- java锁(公平锁和非公平锁、可重入锁(又名递归锁)、自旋锁、独占锁(写)/共享锁(读)/互斥锁、读写锁)
前言 本文对Java的一些锁的概念和实现做个整理,涉及:公平锁和非公平锁.可重入锁(又名递归锁).自旋锁.独占锁(写)/共享锁(读)/互斥锁.读写锁 公平锁和非公平锁 概念 公平锁是指多个线程按照申请 ...
- 乐观锁和悲观锁,可重入锁和不可重入锁(1)
乐观锁和悲观锁,可重入锁和不可重入锁(1) 前言 感觉有一段时间没有写博客了呢.还是再接再厉吧,适当程度的总结能让我自己能够更加深入地巩固和理解自己所学习的一切. 还有,我很懒,而且我还是比较喜欢写日 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等...
http://blog.51cto.com/13919357/2339446 Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容 ...
- Java进阶:ReentrantLock实现原理解析(公平锁、非公平锁、可重入锁、自旋锁)
概述 本篇将介绍公平锁.非公平锁.可重入锁.自旋锁相关理论知识,同时结合相关源码和Demo进行解析,主要是以ReentrantLock作为例子. 公平锁 公平锁定义 公平锁是指线程按照申请所的顺序来获 ...
- 线程调度、公平锁和非公平锁、乐观锁和悲观锁、锁优化、重入锁
1. 线程调度 线程调度指的就是给线程分配使用处理器的过程.主要的调度方式有两种:协同式调度和抢占式调度. 1.1 协同式调度 线程完成自己的任务之后主动通知系统切换到另一个线程上. 优点: 实现简单 ...
- Java锁之可重入锁和递归锁
Java锁之可重入锁和递归锁 目录 Java锁之可重入锁和递归锁基本概念 Java锁之可重入锁和递归锁代码验证 小结 理论,代码,小结,学习三板斧. 1. Java锁之可重入锁和递归锁基本概念 可重入 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等
Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互 ...
- java -锁(公平、非公平锁、可重入锁【递归锁】、自旋锁)
1.公平锁.非公平锁 2.可重入锁(递归锁) 3.自旋锁 AtomicReference atomicReference = new AtomicReference();//原子引用线程 下面代码5秒 ...
- 不可重入锁和可重入锁
不可重入锁也叫自旋锁 指当一个方法调用了锁之后,如持有本锁的另一个方法也想执行,将会进入等待.那么想要使用这个方法必须先释放锁方可调用 public class Lock{private boolea ...
最新文章
- 一文搞懂 Java 泛型,非常详细!
- python自动发微信-python实现微信每日一句自动发送给喜欢的人
- [蓝桥杯2018决赛]换零钞-枚举
- tf.reshape()
- 网页鼠标指针样式(cursor属性)
- iOS - iOS6 越狱及必装源、软件
- 小程序 蓝牙连接(出现的问题和一些解决方法)
- JVM之运行时栈帧的结构(基于《深入理解Java虚拟机》之第八章虚拟机字节码执行引擎)(上)
- 使用pathogen安装vim插件nerdtreee
- 小丁带你走进git世界一-git简单配置
- Vue中key属性的作用
- 全球与中国便携式USB摄像机市场现状及未来发展趋势(2022)
- 操作系统 FIFO 先进先出页面置换算法
- 时间间隔频率计数器及其主要参数
- 电子产品安规测试产品及检测设备
- Towards 3D Human Pose Estimation in the Wild: a Weakly-supervised Approach论文翻译
- [附源码]计算机毕业设计JAVA基于JAVAWEB的高校实训管理系统
- 线性分类器:感知器/SVM
- XPS可以转成Word吗?两种XPS转Word的方法
- 【解决】SX1308无法升压、升压后接上负载电压就被拉低解决办法