美文网首页
并发编程(十):ReentrantLock

并发编程(十):ReentrantLock

作者: codeMover | 来源:发表于2020-04-18 11:31 被阅读0次

    ReentrantLock特性

    • 可中断
    • 可以设置超时时间
    • 可以设置公平锁
    • 支持多个条件变量
    • 支持重入,和synchronized一致

    基本语法

    // 基于ReentrantLock对象保护临界区
    reentarntLock.lock();
    try{
        // 临界区
    }finally{
        // rnnetrantLock.unlock();
    }
    

    可重入

    • 可重入指同一线程如果首次获得了这把锁,如果在获取再获取这把锁,表示可重入

    可打断

    • lockInterruptibly() 锁可打断
      • 如果没有竞争,就会获取lock对象锁
      • 如果有竞争就会进入阻塞队列
      • 可以被其他线程用interrupt方法打断

    锁超时

    • tryLock() 尝试获得锁
    • 使用tryLock()解决哲学家就餐问题,tryLock()返回false说明没能获得锁
    public class PhilosopherProblem {
        public static void main(String[] args) {
            Chopstic c1 = new Chopstic("1");
            Chopstic c2 = new Chopstic("2");
            Chopstic c3 = new Chopstic("3");
            Chopstic c4 = new Chopstic("4");
            Chopstic c5 = new Chopstic("5");
    
            new Philosopher("苏格拉底",c1,c2).start();
            new Philosopher("泊拉图",c2,c3).start();
            new Philosopher("亚里士多德",c3,c4).start();
            new Philosopher("阿基米德",c4,c5).start();
            new Philosopher("米开朗琪罗",c5,c1).start();
        }
    }
    
    @Slf4j(topic = "ants.Philosopher")
    class Philosopher extends Thread{
        Chopstic left;
        Chopstic right;
    
        public Philosopher(String name,Chopstic left,Chopstic right){
            super(name);
            this.left = left;
            this.right = right;
        }
    
        @SneakyThrows
        @Override
        public void run() {
            while (true){
    //            synchronized (left){
    //                synchronized (right){
    //                    eat();
    //                }
    //            }
                if(left.tryLock()){
                    try{
                        if(right.tryLock()){
                            try{
                                eat();
                            }finally {
                                right.unlock();
                            }
                        }
                    }finally {
                        left.unlock();
                    }
                }
            }
        }
        private void eat() throws InterruptedException {
            log.debug("eating...");
            Thread.sleep(1000);
        }
    }
    
    
    class Chopstic extends ReentrantLock {
        private String name;
        public Chopstic(String name){
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "筷子:【"+name+"】";
        }
    }
    

    公平锁

    • ReentrantLock默认是非公平锁,当构造函数时true,使用公平锁
    • 公平锁可以解决姐问题
    • 平时不设置,公平锁降低并发度

    条件变量

    ReentrantLock支持多个条件变量,想比synchronized的waitset

    • synchronized不满足条件的变量都会放在同一个waitset中
    • ReentrantLock中的条件变量支持多个条件变量,一个条件变量想当与一个waitset
    • 使用流程
      • await前需要获得锁
      • await执行后,会释放锁,进入conditionObject等待
      • await的线程被唤醒singnal(打断、超时)时重新竞争lock锁
      • 竞争lock锁成功后,从await后继续执行
    @Slf4j(topic = "ants.ManyCondition")
    public class ManyCondition {
        static volatile boolean t1Status;
        static volatile boolean t2Status;
        static ReentrantLock lock = new ReentrantLock();
        static Condition sta1 = lock.newCondition();
        static Condition sta2 = lock.newCondition();
    
        public static void main(String[] args) {
            new Thread("t1") {
                @SneakyThrows
                @Override
                public void run() {
                    lock.lock();
                    try {
                        while (!t1Status) {
                            sta1.await();
                        }
                        log.debug("t1干了剩下的活");
                    } finally {
                        lock.unlock();
                    }
    
                }
            }.start();
            new Thread("t2") {
                @SneakyThrows
                @Override
                public void run() {
                    lock.lock();
                    try {
                        while (!t2Status) {
                            sta2.await();
                        }
                        log.debug("t2干了剩下的活");
                    } finally {
                        lock.unlock();
                    }
                }
            }.start();
            lock.lock();
            try {
                sta1.signal();
                t1Status = true;
            } finally {
                lock.unlock();
    
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:并发编程(十):ReentrantLock

          本文链接:https://www.haomeiwen.com/subject/znzmvhtx.html