6.23Java多线程可重入锁实现原理
Posted 俊king
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6.23Java多线程可重入锁实现原理相关的知识,希望对你有一定的参考价值。
什么是可重入锁?
-
某个线程试图获取一个已经由它自己持有的锁时,这个请求会立刻成功
-
将这个锁的计数值+1.同时锁住资源
-
当线程退出同步代码块时,计数器将会递减。计数值=0时,锁释放
如果没有可重入锁,第二次获得锁时会进入死锁状态
锁是作为并发共享数据,保证一致性的工具
之前用的锁是内置锁,内部已经设置好了。
可重入锁代码示例
package thread.rearrangement;
/**
* 可重入锁,锁可以延续使用
* @since JDk 1.8
* @date 2021/6/23
* @author Lucifer
*/
public class LockTest {
public void test(){
/**
* 第一次获得锁
*/
synchronized(this){
while(true){
/*第二次获得同样的锁*/
synchronized(this){
System.out.println("ReentrantLock!");
}
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new LockTest().test();
}
}
使用同步方法
class ReentrantLockTest{
public synchronized void a(){
}
public synchronized void b(){
}
/**
* 可重入锁的用法
*/
public synchronized void all(){
this.a();
this.b();
}
}
不可重入锁代码示例
package thread.rearrangement;
/**
* 不可重入锁:表示锁不可以延续使用--->循环
* @since JDK 1.8
* @date 2021/6/23
* @author Lucifer
*/
public class LockTestNo2 {
/*使用锁*/
Lock lock = new Lock();
/*成员方法*/
public void a() throws InterruptedException {
lock.lock();
doSomething();
lock.unlock();
}
/*不可重入--->属性值不能往下面带,用了锁之后不会释放掉*/
public void doSomething() throws InterruptedException {
lock.lock();
//......
lock.unlock();
}
public static void main(String[] args) throws InterruptedException {
LockTestNo2 testNo2 = new LockTestNo2();
testNo2.a();
testNo2.doSomething();
}
}
/**
* 自定义锁的类:这是一个不可重入锁
*/
class Lock{
/*表示是否被占用的属性*/
private boolean isLocked = false;
/*使用锁的方法*/
public synchronized void lock() throws InterruptedException {
/*写一个死循环*/
while (isLocked){
/*加入等待线程*/
wait();
}
/*锁的状态改变*/
isLocked = true;
}
/*释放锁的方法*/
public synchronized void unlock(){
/*属性变为初始化*/
isLocked = false;
/*唤醒资源*/
notifyAll();
}
}
可重入锁demo
实现原理:当线程请求锁时先判断进来的线程是否是当前已持有锁的线程,如果是就直接使用。如果不是就等待
package thread.rearrangement;
/**
* 可重入锁,锁可以延续使用
* 锁可以延续使用,每一个锁都有一个计数器
* @since JDk 1.8
* @date 2021/6/23
* @author Lucifer
*/
public class LockTestNo3 {
/*使用锁*/
ReLock reLock = new ReLock();
/*成员方法*/
public void a() throws InterruptedException {
reLock.lock();
System.out.println(reLock.getHoldCount());
doSomething();
reLock.unlock();
System.out.println(reLock.getHoldCount());
}
/*不可重入--->属性值不能往下面带,用了锁之后不会释放掉*/
public void doSomething() throws InterruptedException {
reLock.lock();
System.out.println(reLock.getHoldCount());
//......
reLock.unlock();
System.out.println(reLock.getHoldCount());
}
public static void main(String[] args) throws InterruptedException {
LockTestNo3 testNo3 = new LockTestNo3();
testNo3.a();
Thread.sleep(1000);
/*查看计数器*/
System.out.println(testNo3.reLock.getHoldCount());
}
}
/**
* 自定义锁的类:这是一个不可重入锁
*/
class ReLock{
/*表示是否被占用的属性*/
private boolean isLocked = false;
/*加入一个存储线程*/
private Thread lockedBy = null;
/*加入一个计数器,统计锁的使用*/
private int holdCount = 0;
/*使用锁的方法*/
public synchronized void lock() throws InterruptedException {
/*取当前线程变量*/
Thread t = Thread.currentThread();
/*写一个死循环*/
while (isLocked&&lockedBy!=t){
/*加入等待线程*/
wait();
}
/*锁的状态改变*/
isLocked = true;
/*把t赋值给lockedBy*/
lockedBy = t;
/*计数器+1*/
holdCount++;
}
/*释放锁的方法*/