Java常用面试题15 synchronized方法的妙用 锁池和等待池的区别

问:

当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B? 


答:

不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。



拓展:

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] view plain copy
  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. }  
 

转载自:http://blog.csdn.net/emailed/article/details/4689220


你可能感兴趣的:(java面试题)