一、将ReentrantLock和synchronized进行比较
1、synchronized和ReentrantLock都是独占锁,不同的是synchronized加锁和解锁过程自动进行;ReentrantLock需手动加锁解锁。
2、synchronized和ReentrantLock都可重入,不同的是synchronized自动进行,不必担心最后是否释放锁;但是ReentrantLock手动进行,加锁和解锁的次数需要完全一样。
可重入演示:
synchronized (this){ System.out.println(Thread.currentThread().getName()+" :synchronized代码块start....."); System.out.println(Thread.currentThread().getName()+" :synchronized代码块sleep....."); Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+" :synchronized代码块voer!!!"); synchronized (this){ System.out.println("重入"); } }
3、相应中断:synchronized不可相应中断;ReentrantLock可以。
二、ReentrantLock的特性
1、简单演示
public class ReentrantLockRunnable implements Runnable{ private ReentrantLock lock = new ReentrantLock(true); @Override public void run() { try{ while (true){ lock.lock(); System.out.println(Thread.currentThread().getName()+"ReenTrant 已加锁"); Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+"sleep....."); } }catch (InterruptedException e){ System.out.println("中断"); e.printStackTrace(); }finally { lock.unlock(); System.out.println(Thread.currentThread().getName()+"ReenTrant 锁已释放!!!!"); } } } import lombok.SneakyThrows; public class ReentrantLockDemo { @SneakyThrows public static void main(String[] args){ Runnable lock = new ReentrantLockRunnable(); Thread thread1 = new Thread(lock); Thread thread2 = new Thread(lock); thread1.start(); thread2.start(); } }
结果:
Thread-0ReenTrant 已加锁 Thread-0sleep..... Thread-0ReenTrant 锁已释放!!!! Thread-1ReenTrant 已加锁 Thread-1sleep..... Thread-1ReenTrant 锁已释放!!!!
2、公平锁
线程获取锁的顺序按照调用lock方法的顺序,慎用!
private ReentrantLock lock = new ReentrantLock(true);
只需要添加true参数即可;不添加或者false参数既是不公平锁,随机获取。
3、响应中断
import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockRunnable implements Runnable{ private ReentrantLock lock = new ReentrantLock(true); private static int count = 0; @Override public void run() { try{ while (true){ lock.lock(); count++; System.out.println(Thread.currentThread().getName()+"ReenTrant 已加锁"); Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+"sleep....."); } }catch (InterruptedException e){ System.out.println("中断"); // e.printStackTrace(); }finally { for(int i=0;i<count;i++){ lock.unlock(); } System.out.println(Thread.currentThread().getName()+"ReenTrant 锁已释放!!!!"); } } } import lombok.SneakyThrows; public class ReentrantLockDemo { @SneakyThrows public static void main(String[] args){ Runnable lock = new ReentrantLockRunnable(); Thread thread1 = new Thread(lock); Thread thread2 = new Thread(lock); thread1.start(); thread2.start(); Thread.sleep(5000); thread1.interrupt(); } }
结果:
Thread-0ReenTrant 已加锁 Thread-0sleep..... Thread-0ReenTrant 已加锁 Thread-0sleep..... Thread-0ReenTrant 已加锁 中断 Thread-0ReenTrant 锁已释放!!!! Thread-1ReenTrant 已加锁 Thread-1sleep..... Thread-1ReenTrant 已加锁 Thread-1sleep..... Thread-1ReenTrant 已加锁 Thread-1sleep..... Thread-1ReenTrant 已加锁 Thread-1sleep..... 。。。。。持续运行
上述代码中加锁几次释放几次,现在把finally中的代码修改:
finally { lock.unlock(); System.out.println(Thread.currentThread().getName()+"ReenTrant 锁已释放!!!!"); }
结果:
Thread-0ReenTrant 已加锁 Thread-0sleep..... Thread-0ReenTrant 已加锁 Thread-0sleep..... Thread-0ReenTrant 已加锁 中断 Thread-0ReenTrant 锁已释放!!!!
Thread-1线程无法进入继续运行,因为锁没有完全释放。加了三次锁,只释放了两次。
5、限时等待
使用tryLock带替lock,设置等待时间,如果取得锁则返回true,如果没有取得则返回false。无参默认不等待,直接返回结果。
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockDome2 implements Runnable{ private ReentrantLock lock = new ReentrantLock(); @Override public void run() { try{ if (lock.tryLock(1, TimeUnit.SECONDS)){ System.out.println(Thread.currentThread().getName()+": 已加锁!"); System.out.println(Thread.currentThread().getName()+": sleep...."); TimeUnit.SECONDS.sleep(5); }else{ System.out.println(Thread.currentThread().getName()+": come here!"); System.out.println(Thread.currentThread().getName()+": over!"); } }catch (InterruptedException e){ System.out.println(Thread.currentThread().getName()+":中断"); }finally { if(lock.isHeldByCurrentThread()){//此锁是否由当前线程持有 lock.unlock(); System.out.println(Thread.currentThread().getName()+": 释放锁!"); } } } public static void main(String[] args){ ReentrantLockDome2 reentrantLockDome2 = new ReentrantLockDome2(); Thread thread1 = new Thread(reentrantLockDome2); Thread thread2 = new Thread(reentrantLockDome2); thread1.start(); thread2.start(); } }
结果:
Thread-0: 已加锁! Thread-0: sleep.... Thread-1: come here! Thread-1: over! Thread-0: 释放锁!
lock.lock();