首页 > 编程语言 > 详细

6.23Java多线程可重入锁实现原理

时间:2021-06-23 21:00:35      阅读:20      评论:0      收藏:0      [点我收藏+]

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++;
?
  }
?
   /*释放锁的方法*/
   public synchronized void unlock(){
?
       /*当前线程=自身的时候释放锁*/
       if (Thread.currentThread()==lockedBy){
?
           /*计数器自减少*/
           holdCount--;
?
           /*计数器为0时候释放锁*/
           if (holdCount==0){
?
               /*改变锁状态*/
               isLocked = false;
?
               /*唤醒资源*/
               notify();
?
               /*重置线程*/
               lockedBy = null;
?
          }
      }
?
       /*属性变为初始化*/
       isLocked = false;
?
       /*唤醒资源*/
       notifyAll();
?
  }
?
?
   /*提供get方法*/
   public int getHoldCount() {
       return holdCount;
  }
}

JUC包下的ReentrantLock类实现了可重入锁的操作

 

6.23Java多线程可重入锁实现原理

原文:https://www.cnblogs.com/JunkingBoy/p/14923081.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!