在java中,每个对象都有两个池,锁(monitor)池和等待池

 

wait() ,notifyAll(),notify() 三个方法都是Object类中的方法.

 

锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

 

等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁),同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.

 

下面通过一个例子来说明:

 

要求写两个线程,一个线程将某个对象的某个成员变量的值加1,而另外一个线程将这个成员变量的值减1.使得该变量的值始终处于[0,2].初始值为0.

在java中,每个对象都有两个池,锁(monitor)池和等待池

 

wait() ,notifyAll(),notify() 三个方法都是Object类中的方法.

 

所以这些线程就进入了该对象的锁池中。

 

同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.

 

下面通过一个例子来说明:

 

要求写两个线程,一个线程将某个对象的某个成员变量的值加1,而另外一个线程将这个成员变量的值减1.使得该变量的值始终处于[0,2].初始值为0.

1. package com.tju;  
2. class Target  
3. {  
4.     private int count;  
5.       
6.     public synchronized void increase()  
7.     {  
8.         if(count == 2)  
9.         {  
10.             try  
11.             {  
12.                 wait();  
13.             }   
14.             catch (InterruptedException e)  
15.             {  
16.                 e.printStackTrace();  
17.             }  
18.         }  
19.         count++;  
20.         System.out.println(Thread.currentThread().getName() + ":" + count);  
21.         notify();  
22.     }  
23.       
24.     public synchronized void decrease()  
25.     {  
26.         if(count == 0)  
27.         {  
28.             try  
29.             {  
30.                 //等待,由于Decrease线程调用的该方法,   
31.                 //所以Decrease线程进入对象t(main函数中实例化的)的等待池,并且释放对象t的锁   
32.                 wait();//Object类的方法   
33.             }  
34.             catch (InterruptedException e)  
35.             {  
36.                 e.printStackTrace();  
37.             }  
38.         }  
39.         count--;  
40.         System.out.println(Thread.currentThread().getName() + ":" + count);  
41.           
42.         //唤醒线程Increase,Increase线程从等待池到锁池   
43.         notify();  
44.     }  
45. }  
46. class Increase extends Thread  
47. {  
48.     private Target t;  
49.       
50.     public Increase(Target t)  
51.     {  
52.         this.t = t;  
53.     }  
54.     @Override  
55.     public void run()  
56.     {     
57.         for(int i = 0 ;i < 30; i++)  
58.         {  
59.             try  
60.             {  
61.                 Thread.sleep((long)(Math.random()*500));  
62.             }  
63.             catch (InterruptedException e)  
64.             {  
65.                 e.printStackTrace();  
66.             }  
67.               
68.             t.increase();  
69.         }  
70.           
71.     }  
72.       
73. }  
74. class Decrease extends Thread  
75. {  
76.       
77.     private Target t;  
78.     public Decrease(Target t)  
79.     {  
80.         this.t = t;  
81.     }  
82.       
83.     @Override  
84.     public void run()  
85.     {  
86.         for(int i = 0 ; i < 30 ; i++)  
87.         {  
88.             try  
89.             {  
90.                 //随机睡眠0~500毫秒   
91.                 //sleep方法的调用,不会释放对象t的锁   
92.                 Thread.sleep((long)(Math.random()*500));  
93.             }  
94.             catch (InterruptedException e)  
95.             {  
96.                 e.printStackTrace();  
97.             }  
98.               
99.             t.decrease();  
100.               
101.         }  
102.           
103.     }  
104.       
105. }  
106.   
107. public class Test  
108. {  
109.     public static void main(String[] args)  
110.     {  
111.         Target t = new Target();  
112.           
113.         Thread t1 = new Increase(t);  
114.         t1.setName("Increase");  
115.         Thread t2 = new Decrease(t);  
116.         t2.setName("Decrease");  
117.           
118.         t1.start();  
119.         t2.start();  
120.     }  
121. }