java 可重入锁 clh_可重入锁(good)

可重入锁,也叫做递归锁,是指在一个线程中可以多次获取同一把锁,

比如:一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法【即可重入】,而无需重新获得锁;

https://www.zhihu.com/question/23284564/answer/29633571

对于不同线程则相当于普通的互斥锁。

在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁

java线程是基于“每线程(per-thread)”,而不是基于“每调用的(per-invocation)”的,也就是说java为每个线程分配一个锁,而不是为每次调用分配一个锁。

最大的作用是避免死锁。

在很多情况下线程需要多次进入锁内执行任务。

我讲一个应用场景就是比如数据库事务的实现过程中。

场景:

add操作将会获取锁,若一个事务当中多次add,就应该允许该线程多次进入该临界区。

synchronized锁也是个可重入锁,

比如一个类当中的两个非静态方法都被synchronized修饰,则线程在获取synchronized锁访问一个方法时是可以进入另一个synchronized方法的

(PS:应该也不能进入static方法的synchronized修饰临界区的,因为是两把不同的锁,表现的不是可重入的特性)

比如我今天遇到的一个场景:用户名和密码保存在本地txt文件中,则登录验证方法和更新密码方法都应该被加synchronized,那么当更新密码的时候需要验证密码的合法性,所以需要调用验证方法,此时是可以调用的。

作者:郭无心

链接:https://www.zhihu.com/question/23284564/answer/68569327

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。

四、可重入锁:

本文里面讲的是广义上的可重入锁,而不是单指JAVA下的ReentrantLock。

可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。

在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁

下面是使用实例

01

public class Testimplements Runnable{

02

03

public synchronized void get(){

04

System.out.println(Thread.currentThread().getId());

05

set();

06

}

07

08

public synchronized void set(){

09

System.out.println(Thread.currentThread().getId());

10

}

11

12

@Override

13

public void run() {

14

get();

15

}

16

public static void main(String[] args) {

17

Test ss=new Test();

18

new Thread(ss).start();

19

new Thread(ss).start();

20

new Thread(ss).start();

21

}

22

}

01

public class Testimplements Runnable {

02

ReentrantLock lock =new ReentrantLock();

03

04

public void get() {

05

lock.lock();

06

System.out.println(Thread.currentThread().getId());

07

set();

08

lock.unlock();

09

}

10

11

public void set() {

12

lock.lock();

13

System.out.println(Thread.currentThread().getId());

14

lock.unlock();

15

}

16

17

@Override

18

public void run() {

19

get();

20

}

21

22

public static void main(String[] args) {

23

Test ss =new Test();

24

new Thread(ss).start();

25

new Thread(ss).start();

26

new Thread(ss).start();

27

}

28

}

两个例子最后的结果都是正确的,即 同一个线程id被连续输出两次。

结果如下:

Threadid: 8

Threadid: 8

Threadid: 10

Threadid: 10

Threadid: 9

Threadid: 9

可重入锁最大的作用是避免死锁

我们以自旋锁作为例子,

01

public class SpinLock {

02

private AtomicReference owner =new AtomicReference<>();

03

public void lock(){

04

Thread current = Thread.currentThread();

05

while(!owner.compareAndSet(null, current)){

06

}

07

}

08

public void unlock (){

09

Thread current = Thread.currentThread();

10

owner.compareAndSet(current,null);

11

}

12

}

对于自旋锁来说,

1、若有同一线程两调用lock() ,会导致第二次调用lock位置进行自旋,产生了死锁

说明这个锁并不是可重入的。(在lock函数内,应验证线程是否为已经获得锁的线程)

2、若1问题已经解决,当unlock()第一次调用时,就已经将锁释放了。实际上不应释放锁。

(采用计数次进行统计)

修改之后,如下:

01

public class SpinLock1 {

02

private AtomicReference owner =new AtomicReference<>();

03

private int count =0;

04

public void lock(){

05

Thread current = Thread.currentThread();

06

if(current==owner.get()) {

07

count++;

08

return ;

09

}

10

11

while(!owner.compareAndSet(null, current)){

12

13

}

14

}

15

public void unlock (){

16

Thread current = Thread.currentThread();

17

if(current==owner.get()){

18

if(count!=0){

19

count--;

20

}else{

21

owner.compareAndSet(current,null);

22

}

23

24

}

25

26

}

27

}

该自旋锁即为可重入锁。

http://ifeve.com/java_lock_see4/

Android 死锁和重入锁

死锁的定义: 1.一般的死锁 一般的死锁是指多个线程的执行必须同时拥有多个资源,由于不同的线程需要的资源被不同的线程占用,最终导致僵持的状态,这就是一般死锁的定义. package com.cxt.t ...

可重入锁 公平锁 读写锁、CLH队列、CLH队列锁、自旋锁、排队自旋锁、MCS锁、CLH锁

1.可重入锁 如果锁具备可重入性,则称作为可重入锁. ========================================== (转)可重入和不可重入 2011-10-04 21:38 这 ...

java ReentrantLock可重入锁功能

1.可重入锁是可以中断的,如果发生了死锁,可以中断程序 //如下程序出现死锁,不去kill jvm无法解决死锁 public class Uninterruptible { public static ...

synchronized关键字,Lock接口以及可重入锁ReentrantLock

多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

可重入锁 &amp&semi; 自旋锁 &amp&semi; Java里的AtomicReference和CAS操作 &amp&semi; Linux mutex不可重入

之前还是写过蛮多的关于锁的文章的: http://www.cnblogs.com/charlesblc/p/5994162.html

Java并发编程-可重入锁

可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍可以获取该锁而不受影响.在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁. publ ...

Java中可重入锁ReentrantLock原理剖析

本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQue ...

ReentrantLock&lpar;重入锁&rpar;以及公平性

ReentrantLock(重入锁)以及公平性 标签(空格分隔): java NIO 如果在绝对时间上,先对锁进行获取的请求一定被先满足,那么这个锁是公平的,反之,是不公平的,也就是说等待时间最长的线 ...

Java多线程——深入重入锁ReentrantLock

简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

随机推荐

Linux内核目录结构

arch 包括所有和体系结构相关的核心代码. include 包括编译内核所需要的大部分头文件 init 包含内核的初始化代码(不是系统的引导代码),有main.c和Version.c两个文件 mm ...

Redis 5种数据结构使用及注意事项

1优缺点 非常非常的快,有测评说比Memcached还快(当大家都是单CPU的时候),而且是无短板的快,读写都一般的快,所有API都差不多快,也没有MySQL Cluster.MongoDB那样更新同 ...

VC&plus;&plus; ADO相关

ADO概述: ADO是Microsoft为最新和最强大的数据访问范例 OLE DB 而设计的,是一个便于使用的应用程序层接口. ADO 使您能够编写应用程序以通过 ...

Yii 如何渲染另一控制器中的视图。

(Yii)使用renderPartial调用另外一个控制器的视图 我们可以使用renderPartial访问存储在不同控制器的视图文件夹中的部分视图文件. 在Yii1.1.3中,我们使用双斜线“//” ...

JSF 2 panelGrid example

In JSF , "h:panelGrid" tag is used to generate HTML table tags to place JSF components in ...

nopCommerce 数据库初试化及数据操作

系统启动时执行任务:IStartupTask,启动时执行的任务主要是数据库的初始化和加载. IStartupTask调用IEfDataProvider进行数据库的初始化. IEfDataProvide ...

H5下拉刷新特效demo,动画流畅

acdream 1408 &quot&semi;Money&comma; Money&comma; Money&quot&semi; (水)

题意:给出一个自然数x,要求找两个自然数a和b,任意多个a和b的组合都不能等于x,且要可以组合成大于x的任何自然数.如果找不到就输出两个0.(输出任意一个满足条件的答案) 思路:x=偶数时,无法构成, ...

LeetCode&lowbar;3 sum closet

Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

windows 下的 Apache SSL证书配置

一.获取证书 1.从腾讯云获取 (1)登录腾讯云后,在“产品”中搜索[ssl]然后会得到 "SSL证书“,进入后点“立即选购” 这样就完成了证书的申请,等待一个工作日的审核. 审核通过后,进 ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值