美文网首页
Java锁之可重入锁

Java锁之可重入锁

作者: bearPotMan | 来源:发表于2019-07-22 21:58 被阅读0次

    可重入锁
    可重入锁也叫递归锁,它俩等同于一回事,指的是同一线程外层函数获得锁之后,内层递归函数仍然能获得该锁的代码,同一线程在外层方法获取锁的时候,再进入内层方法会自动获取锁。也就是说,线程可以进入任何一个它已经拥有的锁所同步着的代码块。ReentrantLock 和 synchronized 就是典型的可重入锁!
    看了上面的解释是不是一脸懵逼,举个通俗易懂的例子来看一下,上代码!
    (1). 基于 synchronized

    public class ReentrantLockTest {
        public static void main(String[] args) {
            Phone phone = new Phone();
            // 第一个线程
            new Thread(() -> {
                phone.sendMsg();
            }, "t1").start();
            // 第二个线程
            new Thread(() -> {
                phone.sendMsg();
            }, "t2").start();
        }
    }
    
    class Phone {
        // 发送短信同步方法
        public synchronized void sendMsg() {
            System.out.println(Thread.currentThread().getName() + " called sendMsg()");
            // 进入另外一个同步着的方法
            sendEmail();
        }
        // 发送邮件同步方法
        public synchronized void sendEmail() {
            System.out.println(Thread.currentThread().getName() + " ******called sendEmail()");
        }
    }
    

    运行结果:

    t1 called sendMsg()             // t1线程在外层方法获取锁的时候
    t1 ******called sendEmail()     // t1再进入内层方法会自动获取锁
    t2 called sendMsg()
    t2 ******called sendEmail()
    

    (2). 基于 ReentrantLock

    public class ReentrantLockTest {
        public static void main(String[] args) {
            Phone phone = new Phone();
            // 第一个线程
            Thread t1 = new Thread(phone, "t1");
            // 第二个线程
            Thread t2 = new Thread(phone, "t2");
    
            t1.start();
            t2.start();
        }
    }
    
    class Phone implements Runnable {
        ReentrantLock lock = new ReentrantLock();
        // 发送短信方法
        public void sendMsg() {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " called sendMsg()");
                // 进入另一个方法
                sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        // 发送邮件方法
        public void sendEmail() {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " ******called sendEmail()");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        @Override
        public void run() {
            sendMsg();
        }
    }
    

    运行结果:

    t1 called sendMsg()             // t1线程在外层方法获取锁的时候
    t1 ******called sendEmail()     // t1再进入内层方法会自动获取锁
    t2 called sendMsg()
    t2 ******called sendEmail()
    

    通过上述代码演示,相对而言会比之前稍微清晰那么一点了吧!

    相关文章

      网友评论

          本文标题:Java锁之可重入锁

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