您的位置:首页 > 编程语言 > Java开发

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


打印结果
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐