java并发之ReentrantLock学习理解
2017-07-27 21:10
609 查看
简介
java多线程中可以使用synchronized关键字来实现线程间同步互斥,但在jdk1.5中新增加了ReentrantLock类也能实现同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定、多路通知分支等功能,并且使用上比synchronized更加灵活。如何使用ReentrantLock
主要是lock.lock()和lock.unlock()两个方法1 public class MyService implements Runnable { 2 3 protected ReentrantLock lock; 4 5 public MyService(ReentrantLock lock){ 6 this.lock = lock; 7 } 8 9 public void run() { 10 lock.lock(); 11 for (int i = 0; i < 5; i++) { 12 System.out.println(Thread.currentThread().getName()+" "+i); 13 try { 14 Thread.sleep(1000); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 lock.unlock(); 20 } 21 22 }
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 8 public static void main(String[] args) { 9 ReentrantLock lock = new ReentrantLock(); 10 for (int i = 0; i < 4; i++) { 11 new Thread(new MyService(lock)).start(); 12 } 13 } 14 }
Thread-0 0 Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 Thread-2 0 Thread-2 1 Thread-2 2 Thread-2 3 Thread-2 4 Thread-3 0 Thread-3 1 Thread-3 2 Thread-3 3 Thread-3 4
使用Condition类实现wait、notify的功能
Condition类也是jdk1.5里出来的,它能实现synchronized和wait、notify搭配的功能,另外比后者更灵活,Condition可以实现多路通知功能,也就是在一个Lock对象里可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择的进行线程通知,在调度线程上更加灵活。而synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有的线程都注册在这个对象上。线程开始notifyAll时,需要通知所有的WAITING线程,没有选择权,会有相当大的效率问题。
使用Condition为什么会报java.lang.IllegalMonitorStateException异常
还是刚才的代码,稍作改动
1 public class MyService implements Runnable { 2 3 protected ReentrantLock lock; 4 protected Condition condition; 5 6 public MyService(ReentrantLock lock,Condition condition){ 7 this.lock = lock; 8 this.condition = condition; 9 } 10 11 public void run() { 12 // lock.lock(); 13 try { 14 condition.await(); 15 } catch (InterruptedException e1) { 16 // TODO Auto-generated catch block 17 e1.printStackTrace(); 18 } 19 for (int i = 0; i < 5; i++) { 20 System.out.println(Thread.currentThread().getName()+" "+i); 21 try { 22 Thread.sleep(1000); 23 } catch (InterruptedException e) { 24 e.printStackTrace(); 25 } 26 } 27 // lock.unlock(); 28 } 29 30 }
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 8 public static void main(String[] args) { 9 ReentrantLock lock = new ReentrantLock(); 10 Condition condition = lock.newCondition(); 11 for (int i = 0; i < 4; i++) { 12 new Thread(new MyService(lock,condition)).start(); 13 } 14 } 15 }
Exception in thread "Thread-0" Exception in thread "Thread-1" Exception in thread "Thread-2" Exception in thread "Thread-3" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source) at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(Unknown Source) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source) at ww.MyService.run(MyService.java:26) at java.lang.Thread.run(Unknown Source)
报错的异常信息是监视器出错,原因是在调用condition.await()之前是要先调用lock.lock()来获得同步监视器。
正确使用Condition类
1 public class MyService implements Runnable { 2 3 protected ReentrantLock lock; 4 protected Condition condition; 5 6 public MyService(ReentrantLock lock,Condition condition){ 7 this.lock = lock; 8 this.condition = condition; 9 } 10 11 public void await(){ 12 try { 13 lock.lock(); 14 System.out.println("await time is "+System.currentTimeMillis()); 15 condition.await(); 16 System.out.println("after await info..."); 17 } catch (InterruptedException e1) { 18 e1.printStackTrace(); 19 } finally { 20 lock.unlock(); 21 } 22 } 23 24 public void signal(){ 25 try { 26 lock.lock(); 27 System.out.println("signal time is "+System.currentTimeMillis()); 28 condition.signal(); 29 } finally { 30 lock.unlock(); 31 } 32 } 33 34 public void run() { 35 await(); 36 } 37 38 }
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 8 public static void main(String[] args) { 9 ReentrantLock lock = new ReentrantLock(); 10 Condition condition = lock.newCondition(); 11 MyService service = new MyService(lock,condition); 12 new Thread(service).start(); 13 try { 14 Thread.sleep(3000); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 service.signal(); 19 } 20 }
await time is 1501142954379 signal time is 1501142957381 after await info...
成功实现等待通知模式,整理一下,下表的方法功能是对应的
Object类 | Condition类 |
Wait() | Await() |
Wait(long timeout) | Await(long time,TimeUnit unit) |
Notify() | Signal() |
notifyAll() | signalAll() |
使用多个Condition实现通知部分线程
1 public class MyService implements Runnable { 2 3 protected ReentrantLock lock; 4 protected Condition conditionA; 5 protected Condition conditionB; 6 7 public MyService(ReentrantLock lock,Condition conditionA,Condition conditionB){ 8 this.lock = lock; 9 this.conditionA = conditionA; 10 this.conditionB = conditionB; 11 } 12 13 public void await_A(){ 14 try { 15 lock.lock(); 16 System.out.println(Thread.currentThread().getName()+" await_A time is "+System.currentTimeMillis()); 17 conditionA.await(); 18 System.out.println(Thread.currentThread().getName()+" after await_A info..."); 19 } catch (InterruptedException e1) { 20 e1.printStackTrace(); 21 } finally { 22 lock.unlock(); 23 } 24 } 25 26 public void await_B(){ 27 try { 28 lock.lock(); 29 System.out.println(Thread.currentThread().getName()+" await_B time is "+System.currentTimeMillis()); 30 conditionB.await(); 31 System.out.println(Thread.currentThread().getName()+" after_B await info..."); 32 } catch (InterruptedException e1) { 33 e1.printStackTrace(); 34 } finally { 35 lock.unlock(); 36 } 37 } 38 39 public void signal_A(){ 40 try { 41 lock.lock(); 42 System.out.println(Thread.currentThread().getName()+" signal_A time is "+System.currentTimeMillis()); 43 conditionA.signal(); 44 } finally { 45 lock.unlock(); 46 } 47 } 48 49 public void signal_B(){ 50 try { 51 lock.lock(); 52 System.out.println(Thread.currentThread().getName()+" signal_B time is "+System.currentTimeMillis()); 53 conditionB.signal(); 54 } finally { 55 lock.unlock(); 56 } 57 } 58 59 public void run() { 60 String tname = Thread.currentThread().getName(); 61 if (tname.equals("A")) { 62 await_A(); 63 } else if (tname.equals("B")) { 64 await_B(); 65 } 66 } 67 68 }
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 8 public static void main(String[] args) { 9 ReentrantLock lock = new ReentrantLock(); 10 11 Condition conditionA = lock.newCondition(); 12 Condition conditionB = lock.newCondition(); 13 MyService service = new MyService(lock,conditionA,conditionB); 14 15 Thread tA = new Thread(service); 16 tA.setName("A"); 17 tA.start(); 18 19 Thread tB = new Thread(service); 20 tB.setName("B"); 21 tB.start(); 22 23 try { 24 Thread.sleep(3000); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 29 service.signal_A(); 30 } 31 }
A await_A time is 1501482321344 B await_B time is 1501482321346 main signal_A time is 1501482324344 A after await_A info...
可以看到只唤醒了A线程。。。
一对一的生产者消费者
1 /** 2 * 生产者和消费者一对一 3 * @author ko 4 * 5 */ 6 public class MyService { 7 8 protected ReentrantLock lock = new ReentrantLock(); 9 protected Condition condition = lock.newCondition(); 10 protected boolean hasValue = false; 11 12 public void set(){ 13 try { 14 lock.lock(); 15 while (hasValue == true) { 16 condition.await(); 17 } 18 System.out.println("★"); 19 hasValue = true; 20 condition.signal(); 21 } catch (InterruptedException e) { 22 // TODO Auto-generated catch block 23 e.printStackTrace(); 24 } finally { 25 lock.unlock(); 26 } 27 } 28 29 public void get(){ 30 try { 31 lock.lock(); 32 while (hasValue == false) { 33 condition.await(); 34 } 35 System.out.println("☆"); 36 hasValue = false; 37 condition.signal(); 38 } catch (InterruptedException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } finally { 42 lock.unlock(); 43 } 44 } 45 46 }
1 /** 2 * 生产者 3 * @author ko 4 * 5 */ 6 public class Producer implements Runnable { 7 8 protected MyService myService; 9 10 public Producer(MyService myService) { 11 super(); 12 this.myService = myService; 13 } 14 15 public void run() { 16 for (int i = 0; i < Integer.MAX_VALUE; i++) { 17 myService.set(); 18 } 19 } 20 21 }
1 /** 2 * 消费者 3 * @author ko 4 * 5 */ 6 public class Customer implements Runnable { 7 8 protected MyService myService; 9 10 public Customer(MyService myService) { 11 super(); 12 this.myService = myService; 13 } 14 15 public void run() { 16 for (int i = 0; i < Integer.MAX_VALUE; i++) { 17 myService.get(); 18 } 19 } 20 21 }
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 8 public static void main(String[] args) { 9 MyService myService = new MyService(); 10 Producer p = new Producer(myService); 11 Customer c = new Customer(myService); 12 13 new Thread(p).start(); 14 new Thread(c).start(); 15 16 } 17 }
打印结果
thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3 thread a 1 thread a 2 thread a 3 thread b 1 thread b 2 thread b 3 thread c 1 thread c 2 thread c 3
打印结果
相关文章推荐
- Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
- JAVA并发编程学习笔记之ReentrantLock
- 聊聊高并发(二十七)解析java.util.concurrent各个组件(九) 理解ReentrantLock可重入锁
- 并发编程学习总结(六) :java 显式锁ReentrantLock使用详解之测试锁与超时
- Java并发学习(十三)-ReentrantReadWriteLock学习
- 聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁
- 聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁
- java并发线程---对锁ReentrantLock的理解
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- 并发编程学习总结(四) :java 显式锁ReentrantLock使用详解之lock()\unlock() 加锁与释放锁
- Java并发包学习--ReentrantLock
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- JAVA并发编程学习笔记之ReentrantLock (r)
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- JAVA并发编程学习笔记之ReentrantLock—推荐-mark
- JAVA并发编程学习笔记之ReentrantLock
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- 并发编程学习总结(五) :java 显式锁ReentrantLock使用详解之条件对象(2)