可重入锁--sychronized锁和lock锁代码详解

这里写目录标题

  • 可重入锁
  • sychronized
  • lock

可重入锁

描述:

可重入锁也叫递归锁。它指的是同一个线程在外层获取锁之后,内层方法也会自动获取锁。lock和sychronized都是可重入锁

作用:

避免死锁

为什么可重入锁可以避免死锁?

public class Widget {
    public synchronized void doSomething(){
        // do something
    }
}
public class LoggingWidget extends Widget {
    public synchronized void doSomething() {
        super.doSomething();
    }
}

现在假设synchronized不是可重入锁。

  1. Widget方法执行需要获得sync锁,默认情况下sync锁的是this,LoggingWidget是Widget的子类。当你执行LoggingWidget中的super.doSomething方法时它就会获得父类的this锁,但父类的this锁被子类抢走之后,没了锁就没法执行完毕。
  2. 这样就出现死锁的现象,子类让父类执行完释放锁,而父类的锁在子类这里没法执行完毕。

现在synchronized是可重入锁

  1. 当进入到LoggingWidget方法时,即使LoggingWidget方法里面有一另一个锁也没关系,它也能获得Widget类中的内容,由于Widget类执行完毕了,LoggingWidget便可以继续执行。

图示:

可重入锁--sychronized锁和lock锁代码详解_第1张图片
method01和method02都是加锁的方法,但是拿到01的锁,即可自动获得02的锁

代码示例:

可重入锁--sychronized锁和lock锁代码详解_第2张图片

sychronized

一个同步方法可以进入另外一个同步方法

// Synchronized
public class Demo01 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(() -> {
            phone.sms();
        }, "A").start();
        new Thread(() -> {
            phone.sms();
        }, "B").start();
    }
}
 
class Phone {
    public synchronized void sms() {
        System.out.println(Thread.currentThread().getName() + "sms");
        call(); // 这里也有锁
    }
 
    public synchronized void call() {
        System.out.println(Thread.currentThread().getName() + "call");
    }
}

lock

sms方法是一个lock锁方法,这个方法调用了call方法,而call方法也是个lock锁方法。可重入锁指一个线程只要能进入sms方法,就也能进入到call方法中

 
public class Demo02 {
    public static void main(String[] args) {
        Phone2 phone = new Phone2();
        new Thread(() -> {
            phone.sms();
        }, "A").start();
        new Thread(() -> {
            phone.sms();
        }, "B").start();
    }
}
 
class Phone2 {
    Lock lock = new ReentrantLock();
 
    public void sms() {
        lock.lock(); // 细节问题:lock.lock(); lock.unlock(); // lock 锁必须配对,否则就会死在里面
        try {
            System.out.println(Thread.currentThread().getName() + "sms");
            call(); // 这里也有锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
 
    public void call() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "call");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

你可能感兴趣的:(⭐【JVM】,可重入锁,sychronized锁,lock锁)