ReenTrantLock和Synchronized

1.jdk中常用的独占锁有两种:Synchronized,ReenTrantLock。两种锁在性能上差别不大,但ReenTrantLock手动加锁,解锁,更加灵活,功能更加丰富
1)独占锁,可重入锁

public class TestReenTrantLock {static Lock lock = new ReentrantLock(true); public static void main(String[] args) { //可重入锁:一个线程多次获取同一个对象上的锁。可重入锁的意义之一在于防止死锁 实现原理:当线程获取锁时,jvm将记录锁的占有者,并将锁中的计数器加1,同一个线程再次获得锁,计数器再次加1。未被占用的锁,计数器为0。当线程退出同步块,计数器值将递减,直到计数器值为0,锁被释放。其他线程才能获得锁 独占锁:一个锁一次只能被一个线程占有 method(); method1(); lock.unlock(); lock.unlock(); }public static void method(){ lock.lock(); System.out.println("第一次获取锁"); }public static void method1(){ lock.lock(); System.out.println("第二次获取锁"); } }

这里在method中获取了TestReenTrantLock类锁,调用method1时再一次获取了TestReenTrantLock类锁,这就是可重入锁
【ReenTrantLock和Synchronized】2)可以实现公平锁
public class FairReenTrantLock {/** * 公平锁:当锁可用时,在锁上等待时间最长的线程获取锁的使用权 * 无参数或为fasle,为非公平锁 * 非公平锁:随机获得锁的使用权 */ static Lock lock = new ReentrantLock(true); public static void main(String[] args) { for (int i=0; i<5; i++){ new Thread(new ThreadDemo()).start(); } }static class ThreadDemo implements Runnable{public ThreadDemo(){}@Override public void run() { try { TimeUnit.SECONDS.sleep(2); }catch (Exception e){ e.printStackTrace(); } for(int i=0; i<2; i++){ lock.lock(); System.out.println("获得锁的线程"+Thread.currentThread().getName()); lock.unlock(); } } }}

ReenTrantLock和Synchronized
文章图片

ReenTrantLock和Synchronized
文章图片

3)可以响应线程中断
  • 首先了解一下 public void interrupt(); (属于ThreadL类)
    ReenTrantLock和Synchronized
    文章图片
public class TestInterrupt {public static void main(String[] args) throws InterruptedException { Thread testThread = new TestThread(); testThread.start(); testThread.interrupt(); }/* *下面测试的三个方法都会阻塞线程,如果没有使用这个三个方法,线程会直接走完, *而且isInterrupted()为true *使用了其中一个,会抛出InterruptedException,isInterrupted()为false */ static class TestThread extends Thread {@Override public void run() { System.out.println("线程开始运行"); try { //TimeUnit.SECONDS.sleep(5); //wait(); join(); }catch (Exception e){ System.out.println("线程发生异常"+e); System.out.println(Thread.currentThread().isInterrupted()); } System.out.println("线程结束运行"); } } }

  • 响应中断案例
public class LockInterruptibly {static Lock firstLock = new ReentrantLock(); static Lock secondLock = new ReentrantLock(); public static void main(String[] args) { Thread firstthread = new Thread(new ThreadDemo(firstLock,secondLock)); Thread secondThread = new Thread(new ThreadDemo(secondLock,firstLock)); firstthread.start(); secondThread.start(); firstthread.interrupt(); }static class ThreadDemo implements Runnable { private Lock firstLock; private Lock secondLock; public ThreadDemo(Lock firstLock,Lock secondLock){ this.firstLock = firstLock; this.secondLock = secondLock; }//会中断处于等待的线程,释放锁,然后另一个线程获取锁,继续走 @Override public void run() { try { firstLock.lockInterruptibly(); TimeUnit.SECONDS.sleep(1); secondLock.lockInterruptibly(); }catch (Exception e){ e.printStackTrace(); }finally { firstLock.unlock(); secondLock.unlock(); System.out.println(Thread.currentThread().getName()+"正常结束"); } } } }

  • 不响应中断案例
public class TestSynchronized {static Object resource1 = new Object(); static Object resource2 = new Object(); public static void main(String[] args) { Thread thread1 = new TestSynchronizedThread(resource1,resource2); Thread thread2 = new TestSynchronizedThread(resource2,resource1); thread1.start(); thread2.start(); thread1.interrupt(); //中断线程, }static class TestSynchronizedThread extends Thread { Object resource1; Object resource2; public TestSynchronizedThread(Object resource1,Object resource2){ this.resource1 = resource1; this.resource2 = resource2; }//即使跑出异常,也不会中断线程,两个线程继续互相等待资源,造成死锁 @Override public void run() { synchronized (resource1){ System.out.println(Thread.currentThread().getName()+"--111"); try { TimeUnit.SECONDS.sleep(1); System.out.println(Thread.currentThread().getName()+"--222"); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName()+"--333"); }System.out.println(Thread.currentThread().getName()+"--444"); synchronized (resource2){ System.out.println(555); } }} } }

4)获取锁时,限时等待
5)利用condition实现等待通知机制,
6)condition实现阻塞队列
synchronized

    推荐阅读