Java - 各种锁的理解与实现-2

1. 公平锁与非公平锁

 1)公平锁

  当多个线程按照申请锁的顺序排队获取锁,获取不到锁的进入阻塞队列,按照顺序依次获取锁

Lock lock= new ReentrantLock(true);

 2)非公平锁

        多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程先获得锁,在高并发的场景下,有可能造成优先级反转或者某个线程一直得不到锁

  synchronized 是非公平锁

  ReentrantLock 可以进行选择设置,默认是非公平锁

Lock lock= new ReentrantLock(false);
// 默认是 false
Lock lock= new ReentrantLock();

2. 可重入锁

        可重入锁:当已获取锁的线程,在访问该锁资源的其余代码时,无需再获取锁,可直接进入,称之为可重入锁;可重入锁能有效避免死锁的情况

 public class  Phone {
    // 类锁
    public static synchronized void sendEmail(){
        sendSMS(Thread.currentThread().getName());
        System.out.println("-----sendEmail");
    }
    // 类锁
    public static synchronized void sendSMS(String threadName){
        System.out.println(threadName + "-----sendSMS");
    }
    public void sendHello(){
        System.out.println("-----sendHello");
    }
     public static void main(String[] args) {
         Phone phone = new Phone();

         new Thread(()->{
             phone.sendEmail();
         },"t1").start();

         new Thread(()->{
             phone.sendSMS(Thread.currentThread().getName());
         },"t2").start();

         new Thread(()->{
             phone.sendHello();
         },"t3").start();
     }
}

执行结果:

Java - 各种锁的理解与实现-2_第1张图片

         当 t1 线程获得类锁之后,去调用 sendSMS 需要获得该方法的类锁,但是之前在执行 sendEmail 时候已经获得该类锁,所以此时无需再次获得,直接执行,这个就叫可重入锁;synchronized 和 ReentrantLock 都是可重入锁,当 t1 执行完毕后,释放了类锁,t2 线程才能进入其执行方法 sendSMS

ReentrantLock 和 synchronized 都是悲观锁,非公平锁,可重入锁

3. Lock 接口及其实现类 ReentrantLock

  Java 中默认对资源上锁使用 synchronized 关键字,但是 synchronized 关键字功能有限,Java 1.5以后又在 JUC 包下设计了一个新的一套对资源上锁和解锁的代码

Lock 接口以及其实现类

Java - 各种锁的理解与实现-2_第2张图片

 使用方式:

// 获取ReentrantLock对象
private ReentrantLock lock = new ReentrantLock();

// 加锁 获取不到锁一直等待直到获取锁
lock.lock();

try {
	System.out.println("this a thread lock");
}finally {

	// 释放锁 如果不释放其他线程就获取不到锁
	lock.unlock();
}

synchronized 和 ReentrantLock区别:

        synchronized 会自动加锁和释放锁        

        synchronized 可以用在普通方法上、使用在静态方法上、使用在代码块中

        ReentrantLock 只能在代码块中使用

        ReentrantLock 需要手动调用 lock() 方法和 unlock() 方法加锁和释放锁

        ReentrantLock 配合 condition 使用能够更加精准的加锁和释放锁

你可能感兴趣的:(Java,Lock,java,开发语言,jvm)