zoukankan      html  css  js  c++  java
  • 可重入锁/不可重入锁

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11395621.html

    可重入锁

    可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提是同一个对象或者类)

    Note:

    ReentrantLock和synchronized都是可重入锁

     1 public class TestLock {  
     2     public synchronized void test1() throws InterruptedException {  
     3         Thread.sleep(1000);  
     4         System.out.println("test1 invoked...");  
     5         test2();  
     6     }  
     7   
     8     public synchronized void test2() throws InterruptedException {  
     9         Thread.sleep(1000);  
    10         System.out.println("test2 invoked...");  
    11     }  
    12   
    13     public static void main(String[] args) throws InterruptedException {  
    14         TestLock testLock = new TestLock();  
    15         testLock.test1();  
    16     }  
    17 }

    上面的代码就是一个可重入锁的一个特点,如果不是可重入锁的话,test2可能不会被当前线程执行,可能造成死锁。 

    不可重入锁

    不可重入锁,与可重入锁相反,不可递归调用,递归调用就会发生死锁。

    使用自旋锁来模拟一个不可重入锁

     1 import java.util.concurrent.atomic.AtomicReference;  
     2   
     3 public class UnreentrantLockTest {  
     4     private static UnreentrantLock lock = new UnreentrantLock();  
     5   
     6     public static void main(String[] args) {  
     7         lock.lock();  
     8   
     9         test();  
    10   
    11         lock.unlock();  
    12     }  
    13   
    14     private static void test() {  
    15         lock.lock();  
    16   
    17         System.out.println("test invoked...");  
    18   
    19         lock.unlock();  
    20     }  
    21   
    22     private static class UnreentrantLock {  
    23         private AtomicReference<Thread> owner = new AtomicReference<>();  
    24   
    25         public void lock() {  
    26             Thread currentThread = Thread.currentThread();  
    27   
    28             for (; ; ) {  
    29                 System.out.println(owner);  
    30                 if (owner.compareAndSet(null, currentThread)) {  
    31                     System.out.println(currentThread + " locked...");  
    32                     return;  
    33                 }  
    34             }  
    35         }  
    36   
    37         public void unlock() {  
    38             Thread currentThread = Thread.currentThread();  
    39   
    40             owner.compareAndSet(currentThread, null);  
    41   
    42             System.out.println(currentThread + " unlock...");  
    43         }  
    44     }  
    45 }  

    Note:

    使用原子引用来存放线程,同一个线程两次调用lock()方法,如果不执行unlock()释放锁的话,第二次调用自旋的时候就会产生死锁,这个锁是不可重入的

    修改上述代码,将它改造成可重入锁,在执行每次操作之前,判断当前锁持有者是否是当前对象,采用state计数

     1 import java.util.concurrent.atomic.AtomicReference;  
     2   
     3 public class ReentrantLockTest {  
     4     private static ReentrantLock lock = new ReentrantLock();  
     5   
     6     public static void main(String[] args) {  
     7         lock.lock();  
     8   
     9         test();  
    10   
    11         lock.unlock();  
    12     }  
    13   
    14     private static void test() {  
    15         lock.lock();  
    16   
    17         System.out.println("test invoked...");  
    18   
    19         test1();  
    20   
    21         lock.unlock();  
    22     }  
    23   
    24     private static void test1() {  
    25         lock.lock();  
    26   
    27         System.out.println("test2 invoked...");  
    28   
    29         lock.unlock();  
    30     }  
    31   
    32     private static class ReentrantLock {  
    33         private AtomicReference<Thread> owner = new AtomicReference<>();  
    34         private int state = 0;  
    35   
    36         public void lock() {  
    37             Thread currentThread = Thread.currentThread();  
    38   
    39             if (currentThread == owner.get()) {  
    40                 state++;  
    41                 return;  
    42             }  
    43   
    44             for (; ; ) {  
    45                 System.out.println(owner);  
    46                 if (!owner.compareAndSet(null, currentThread)) {  
    47                     return;  
    48                 }  
    49             }  
    50         }  
    51   
    52         public void unlock() {  
    53             Thread currentThread = Thread.currentThread();  
    54   
    55             if (currentThread == owner.get()) {  
    56                 if (state != 0) {  
    57                     state--;  
    58                 } else {  
    59                     owner.compareAndSet(currentThread, null);  
    60                 }  
    61             }  
    62         }  
    63     }  
    64 }  
  • 相关阅读:
    【磁盘/文件系统】第五篇:CentOS7.x__btrfs文件系统详解
    【python】-- IO多路复用(select、poll、epoll)介绍及实现
    【python】-- 事件驱动介绍、阻塞IO, 非阻塞IO, 同步IO,异步IO介绍
    【python】-- 协程介绍及基本示例、协程遇到IO操作自动切换、协程(gevent)并发爬网页
    【python】-- 多进程的基本语法 、进程间数据交互与共享、进程锁和进程池的使用
    【python】-- 队列(Queue)、生产者消费者模型
    【python】-- 信号量(Semaphore)、event(红绿灯例子)
    【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)
    【python】-- 继承式多线程、守护线程
    【python】-- 进程与线程
  • 原文地址:https://www.cnblogs.com/agilestyle/p/11395621.html
Copyright © 2011-2022 走看看