锁 Lock重入锁写入锁
Posted here
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了锁 Lock重入锁写入锁相关的知识,希望对你有一定的参考价值。
ReentrantLock 重入锁 类似于synchronize 区别与写法上,在需要进行同步的代码部分加上锁定,但不要忘记最后一定要释放锁定,
不然会造成锁永远无法释放,其他线程永远进不来的结果。
eg:
1 package com.zym.height.Lock01; 2 3 import java.util.concurrent.locks.Lock; 4 import java.util.concurrent.locks.ReentrantLock; 5 6 public class UseReentrantLock { 7 8 private Lock lock = new ReentrantLock(); 9 10 public void method1(){ 11 try { 12 lock.lock(); 13 System.out.println("当前线程:" + Thread.currentThread().getName() + "进入method1.."); 14 Thread.sleep(1000); 15 System.out.println("当前线程:" + Thread.currentThread().getName() + "退出method1.."); 16 Thread.sleep(1000); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } finally { 20 21 lock.unlock(); 22 } 23 } 24 25 public void method2(){ 26 try { 27 lock.lock(); 28 System.out.println("当前线程:" + Thread.currentThread().getName() + "进入method2.."); 29 Thread.sleep(2000); 30 System.out.println("当前线程:" + Thread.currentThread().getName() + "退出method2.."); 31 Thread.sleep(1000); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } finally { 35 36 lock.unlock(); 37 } 38 } 39 40 public static void main(String[] args) { 41 42 final UseReentrantLock ur = new UseReentrantLock(); 43 Thread t1 = new Thread(new Runnable() { 44 @Override 45 public void run() { 46 ur.method1(); 47 ur.method2(); 48 } 49 }, "t1"); 50 51 t1.start(); 52 try { 53 Thread.sleep(10); 54 } catch (InterruptedException e) { 55 e.printStackTrace(); 56 } 57 //System.out.println(ur.lock.getQueueLength()); 58 } 59 60 61 }
Lock Condition
公平锁和非公平锁
Lock lock = new ReentrantLock();
lock用法:
tryLock():尝试获得锁(在给定的时间内尝试获得锁),获得结果用true/false返回。
isFair():是否是公平锁。
isLocked():是否锁定。
getHoldCount():查询当前线程保持此锁的个数,也就是调用lock()次数。
lockInterruptibly():优先响应中断的锁。
getQueueLength():返回正在等待获取此锁的线程数。
getWaitQueueLength():返回等待与锁定相关的给定条件Condition的线程数。
hasQueuedThread(Thread thread):查询指定的线程是否正在等待此锁。
hasQueuedThreads():查询是否有线程正在等待此锁。
hasWaiters():查询是否有线程正在等待与此锁定有关的condition条件。
1 package com.zym.height.Lock01; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class UseCondition { 8 9 private Lock lock = new ReentrantLock(); 10 private Condition condition = lock.newCondition(); 11 12 public void method1(){ 13 try { 14 lock.lock(); 15 System.out.println("当前线程:" + Thread.currentThread().getName() + "进入等待状态.."); 16 Thread.sleep(3000); 17 System.out.println("当前线程:" + Thread.currentThread().getName() + "释放锁.."); 18 condition.await(); // Object wait 19 System.out.println("当前线程:" + Thread.currentThread().getName() +"继续执行..."); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } finally { 23 lock.unlock(); 24 } 25 } 26 27 public void method2(){ 28 try { 29 lock.lock(); 30 System.out.println("当前线程:" + Thread.currentThread().getName() + "进入.."); 31 Thread.sleep(3000); 32 System.out.println("当前线程:" + Thread.currentThread().getName() + "发出唤醒.."); 33 condition.signal(); //Object notify 34 } catch (Exception e) { 35 e.printStackTrace(); 36 } finally { 37 lock.unlock(); 38 } 39 } 40 41 public static void main(String[] args) { 42 43 final UseCondition uc = new UseCondition(); 44 Thread t1 = new Thread(new Runnable() { 45 @Override 46 public void run() { 47 uc.method1(); 48 } 49 }, "t1"); 50 Thread t2 = new Thread(new Runnable() { 51 @Override 52 public void run() { 53 uc.method2(); 54 } 55 }, "t2"); 56 t1.start(); 57 58 t2.start(); 59 } 60 61 62 63 }
1 package com.zym.height.Lock01; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.ReentrantLock; 5 6 public class UseManyCondition { 7 8 private ReentrantLock lock = new ReentrantLock(); 9 private Condition c1 = lock.newCondition(); 10 private Condition c2 = lock.newCondition(); 11 12 public void m1(){ 13 try { 14 lock.lock(); 15 System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m1等待.."); 16 c1.await(); 17 System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m1继续.."); 18 } catch (Exception e) { 19 e.printStackTrace(); 20 } finally { 21 lock.unlock(); 22 } 23 } 24 25 public void m2(){ 26 try { 27 lock.lock(); 28 System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m2等待.."); 29 c1.await(); 30 System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m2继续.."); 31 } catch (Exception e) { 32 e.printStackTrace(); 33 } finally { 34 lock.unlock(); 35 } 36 } 37 38 public void m3(){ 39 try { 40 lock.lock(); 41 System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m3等待.."); 42 c2.await(); 43 System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m3继续.."); 44 } catch (Exception e) { 45 e.printStackTrace(); 46 } finally { 47 lock.unlock(); 48 } 49 } 50 51 public void m4(){ 52 try { 53 lock.lock(); 54 System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒.."); 55 c1.signalAll(); 56 } catch (Exception e) { 57 e.printStackTrace(); 58 } finally { 59 lock.unlock(); 60 } 61 } 62 63 public void m5(){ 64 try { 65 lock.lock(); 66 System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒.."); 67 c2.signal(); 68 } catch (Exception e) { 69 e.printStackTrace(); 70 } finally { 71 lock.unlock(); 72 } 73 } 74 75 public static void main(String[] args) { 76 77 78 final UseManyCondition umc = new UseManyCondition(); 79 Thread t1 = new Thread(new Runnable() { 80 @Override 81 public void run() { 82 umc.m1(); 83 } 84 },"t1"); 85 Thread t2 = new Thread(new Runnable() { 86 @Override 87 public void run() { 88 umc.m2(); 89 } 90 },"t2"); 91 Thread t3 = new Thread(new Runnable() { 92 @Override 93 public void run() { 94 umc.m3(); 95 } 96 },"t3"); 97 Thread t4 = new Thread(new Runnable() { 98 @Override 99 public void run() { 100 umc.m4(); 101 } 102 },"t4"); 103 Thread t5 = new Thread(new Runnable() { 104 @Override 105 public void run() { 106 umc.m5(); 107 } 108 },"t5"); 109 110 t1.start(); // c1 111 t2.start(); // c1 112 t3.start(); // c2 113 114 115 try { 116 Thread.sleep(2000); 117 } catch (InterruptedException e) { 118 e.printStackTrace(); 119 } 120 121 t4.start(); // c1 122 try { 123 Thread.sleep(2000); 124 } catch (InterruptedException e) { 125 e.printStackTrace(); 126 } 127 t5.start(); // c2 128 129 } 130 131 132 133 }
1 package com.zym.height.Lock01; 2 3 import java.util.concurrent.locks.ReentrantLock; 4 /** 5 * lock.getHoldCount()方法:只能在当前调用线程内部使用,不能再其他线程中使用 6 * 那么我可以在m1方法里去调用m2方法,同时m1方法和m2方法都持有lock锁定即可 测试结果holdCount数递增 7 * 8 */ 9 public class TestHoldCount { 10 11 //重入锁 12 private ReentrantLock lock = new ReentrantLock(); 13 14 public void m1(){ 15 try { 16 lock.lock(); 17 System.out.println("进入m1方法,holdCount数为:" + lock.getHoldCount()); 18 19 //调用m2方法 20 m2(); 21 22 } catch (Exception e) { 23 e.printStackTrace(); 24 } finally { 25 lock.unlock(); 26 } 27 } 28 29 public void m2(){ 30 try { 31 lock.lock(); 32 System.out.println("进入m2方法,holdCount数为:" + lock.getHoldCount()); 33 } catch (Exception e) { 34 e.printStackTrace(); 35 } finally { 36 lock.unlock(); 37 } 38 } 39 40 41 public static void main(String[] args) { 42 TestHoldCount thc = new TestHoldCount(); 43 thc.m1(); 44 } 45 }
ReentrantReadWriteLock
读写锁 其核心就是实现读写分离的锁,在高并发访问下,尤其是读多写少的情况下,性能要远高于重入锁,在同一时间,只能有一个线程
可以进行访问被锁定的代码,那么读写锁则不同,其本质是分层两个锁,即读锁、写锁。在读锁下,多个线程可以并发的进行访问,
但是在写锁的时候,只能一个一个的顺序访问。
口诀:读读共享,写写互斥,读写互斥。
1 package com.zym.height.Lock01; 2 3 import java.util.concurrent.locks.ReentrantReadWriteLock; 4 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; 5 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; 6 7 public class UseReentrantReadWriteLock { 8 9 private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); 10 private ReadLock readLock = rwLock.readLock(); 11 private WriteLock writeLock = rwLock.writeLock(); 12 13 public void read(){ 14 try { 15 readLock.lock(); 16 System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..."); 17 Thread.sleep(3000); 18 System.out.println("当前线程:" + Thread.currentThread().getName() + "退出..."); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } finally { 22 readLock.unlock(); 23 } 24 } 25 26 public void write(){ 27 try { 28 writeLock.lock(); 29 System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..."); 30 Thread.sleep(3000); 31 System.out.println("当前线程:" + Thread.currentThread().getName() + "退出..."); 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } finally { 35 writeLock.unlock(); 36 } 37 } 38 39 public static void main(String[] args) { 40 41 final UseReentrantReadWriteLock urrw = new UseReentrantReadWriteLock(); 42 43 Thread t1 = new Thread(new Runnable() { 44 @Override 45 public void run() { 46 urrw.read(); 47 } 48 }, "t1"); 49 Thread t2 = new Thread(new Runnable() { 50 @Override 51 public void run() { 52 urrw.read(); 53 } 54 }, "t2"); 55 Thread t3 = new Thread(new Runnable() { 56 @Override 57 public void run() { 58 urrw.write(); 59 } 60 }, "t3"); 61 Thread t4 = new Thread(new Runnable() { 62 @Override 63 public void run() { 64 urrw.write(); 65 } 66 }, "t4"); 67 68 // t1.start(); 69 // t2.start(); 70 71 // t1.start(); // R 72 // t3.start(); // W 73 74 t3.start(); 75 t4.start(); 76 77 78 79 80 81 82 83 84 } 85 }
以上是关于锁 Lock重入锁写入锁的主要内容,如果未能解决你的问题,请参考以下文章