zoukankan      html  css  js  c++  java
  • 并发编程-concurrent指南-Lock-可重入锁(ReentrantLock)

    可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法A,这个线程在没有释放这把锁的时候,能否再次进入方法A呢?

    • 可重入锁:可以再次进入方法A,就是说在释放锁前此线程可以再次进入方法A(方法A递归)。
    • 不可重入锁(自旋锁):不可以再次进入方法A,也就是说获得锁进入方法A是此线程在释放锁钱唯一的一次进入方法A。

    ,具体区别查看可重入锁和不可重入锁区别

    ReentrantLock,意思是“可重入锁”。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。下面通过一些实例看具体看一下如何使用ReentrantLock。

    lock()的正确使用方法

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MainLock {
        private Lock lock = new ReentrantLock();
        public static void main(String[] args) {
            final MainLock mainLock = new MainLock();
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mainLock.insert(Thread.currentThread());
                }
            }).start();
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mainLock.insert(Thread.currentThread());
                }
            }).start();
        }
    
        public void insert(Thread thread){
            lock.lock();//获取锁
            try{
                System.out.println(thread.getName() + "获取锁");
                for(int i=0;i<5;i++){
                    System.out.println("------------------------" + thread.getName() + ":"+i+"------------------------");
                }
            }finally {
                System.out.println(thread.getName() + "释放锁");
                lock.unlock();//释放锁
            }
        }
    }

    结果:

    Thread-0获取锁
    ------------------------Thread-0:0------------------------
    ------------------------Thread-0:1------------------------
    ------------------------Thread-0:2------------------------
    ------------------------Thread-0:3------------------------
    ------------------------Thread-0:4------------------------
    Thread-0释放锁
    Thread-1获取锁
    ------------------------Thread-1:0------------------------
    ------------------------Thread-1:1------------------------
    ------------------------Thread-1:2------------------------
    ------------------------Thread-1:3------------------------
    ------------------------Thread-1:4------------------------
    Thread-1释放锁

    tryLock()的使用方法

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MainTryLock {
        private Lock lock = new ReentrantLock();
        public static void main(String[] args) {
            final MainTryLock mainTryLock = new MainTryLock();
    
            new Thread(){
                @Override
                public void run() {
                    mainTryLock.insert(Thread.currentThread());
                }
            }.start();
    
            new Thread(){
                @Override
                public void run() {
                    mainTryLock.insert(Thread.currentThread());
                }
            }.start();
        }
    
        public void insert(Thread thread){
            if(lock.tryLock()){
                try{
                    System.out.println(thread.getName() + "获取锁");
                    for(int i=0;i<5;i++){
                        Thread.sleep(200);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    System.out.println(thread.getName() + "释放锁");
                    lock.unlock();//释放锁
                }
            }else{
                System.out.println(thread.getName()+"未获取到锁");
            }
        }
    }

    结果:

    Thread-0获取锁
    Thread-1未获取到锁
    Thread-0释放锁

    lockInterruptibly()响应中断的使用方法:

    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MainLockInterruptibl {
        private  Lock lock = new ReentrantLock();
        public static void main(String[] args)  {
            MainLockInterruptibl test = new MainLockInterruptibl();
            MyThread thread1 = new MyThread(test);
            MyThread thread2 = new MyThread(test);
            thread1.start();
            thread2.start();
    
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            thread2.interrupt();
        }
    
        public void insert(Thread thread) throws InterruptedException{
            lock.lockInterruptibly();   //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出
            try {
                System.out.println(thread.getName()+"得到了锁");
                long startTime = System.currentTimeMillis();
                for( int i=0;i<5;i++) {
                    TimeUnit.SECONDS.sleep(2);
                }
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                System.out.println(Thread.currentThread().getName()+"执行finally");
                lock.unlock();
                System.out.println(thread.getName()+"释放了锁");
            }
        }
        static class MyThread extends Thread {
            private MainLockInterruptibl test = null;
            public MyThread(MainLockInterruptibl test) {
                this.test = test;
            }
            @Override
            public void run() {
                try {
                    test.insert(Thread.currentThread());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()+"被中断");
                }
            }
        }
    }

    结果:

    Thread-0得到了锁
    java.lang.InterruptedException
    Thread-1被中断
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
        at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
        at com.concurrent.MainLockInterruptibl.insert(MainLockInterruptibl.java:25)
        at com.concurrent.MainLockInterruptibl$MyThread.run(MainLockInterruptibl.java:48)
    Thread-0执行finally
    Thread-0释放了锁

    源码地址:https://github.com/qjm201000/concurrent_reentrantLock.git

  • 相关阅读:
    【个人实战】作品展播BI大屏【部分见github主页】
    JAVA设计模式之单例(singleton)
    你所不知道的redis安装方法,穿一手鞋,看一手资料
    zookeeper实现分布式锁总结,看这一篇足矣(设计模式应用实战)
    JAVA设计模式之状态模式(state)
    JAVA设计模式之适配器模式(adapter)
    JAVA设计模式之构建器模式(builder)
    Redis实现分布式锁(设计模式应用实战)
    JAVA设计模式之享元模式(flyweight)
    JAVA设计模式之组合模式(composite)
  • 原文地址:https://www.cnblogs.com/qjm201000/p/10175489.html
Copyright © 2011-2022 走看看