synchronized锁重入

Posted on 2016-11-17 20:27  锕宇  阅读(442)  评论(0)    收藏  举报
  1. package synLockIn_1;
  2. /* synchronized锁重入,当一个线程得到一个对象锁且还未释放锁时,再次请求此对象锁时可以再次得到该对象的锁
  3.  * 此例中线程1进入Service类的service_1方式时,得到了Lock锁,在这个方法内便可以再次访问service_2方法
  4.  * 而此时由于对象锁没被释放,线程2无法访问service_1方法*/
  5. class Service{
  6.  synchronized public void service1(){
  7.   System.out.println(Thread.currentThread().getName()+" service_1");
  8.   try{
  9.    Thread.sleep(1000);
  10.   }catch(InterruptedException ie){
  11.    ie.printStackTrace();
  12.   }
  13.   service2();
  14.  }
  15.  synchronized public void service2(){
  16.   System.out.println(Thread.currentThread().getName()+" service_2");
  17.   try{
  18.    Thread.sleep(1000);
  19.   }catch(InterruptedException ie){
  20.    ie.printStackTrace();
  21.   }
  22.   service3();
  23.  }
  24.  synchronized public void service3(){
  25.   System.out.println(Thread.currentThread().getName()+" service_3");
  26.   try{
  27.    Thread.sleep(1000);
  28.   }catch(InterruptedException ie){
  29.    ie.printStackTrace();
  30.   }
  31.  }
  32. }
  33. class MyThread extends Thread{
  34.  Service service;
  35.  public MyThread(Service service){
  36.   this.service = service;
  37.  }
  38.  @Override
  39.  public void run(){
  40.   service.service1();
  41.  }
  42. }
  43. public class Run {
  44.  public static void main(String[] args) {
  45.   Service service = new Service(); //两个线程共享同一个Service对象,使得两个线程访问一个对象,JVM只产生一个对象锁
  46.   MyThread t = new MyThread(service);
  47.   t.start();
  48.   MyThread t1 = new MyThread(service);
  49.   t1.start();
  50.  }
  51. }

运行结果如下

  从运行结果中可以看出线程Thread-1先访问了service_1同步方法,输出Thread-1 service_1后停留1秒。对象锁还没释放,且两个线程共享同一个类,所以线程Thread-0无法访问service_1方法。而Thread-1还没释放对象锁,但可以重新获得对象锁继续访问service_2同步方法。

  可重入锁也支持在父子类继承的环境中。

  1. package synLockIn2;
  2. /* synchronized锁重入,当一个线程得到一个对象锁且还未释放锁时,再次请求此对象锁时可以再次得到该对象的锁 */
  3. class Main {
  4.  public int i = 10;
  5.  synchronized public void operateIMainMethod(){
  6.   try{
  7.    System.out.println( Thread.currentThread().getName()+" main print i="+i);
  8.    i--;
  9.    Thread.sleep(100);
  10.   }catch(InterruptedException ie){
  11.    ie.printStackTrace();
  12.   }
  13.  }
  14. }
  15. class Sub extends Main {
  16.  synchronized public void operateIMainMethod(){
  17.   System.out.println(Thread.currentThread().getName()+" 线程开始!!");
  18.   try{
  19.    while( i > 0 ){
  20.     System.out.println( Thread.currentThread().getName()+" sub print i=" + i);
  21.     i--;
  22.     Thread.sleep(100);
  23.     super.operateIMainMethod();
  24.    }
  25.   }catch(InterruptedException ie){
  26.    ie.printStackTrace();
  27.   }
  28.   System.out.println(Thread.currentThread().getName()+" 线程结束!!");
  29.  }
  30. }
  31. class MyThread extends Thread{
  32.  Sub sub = new Sub();
  33.  MyThread(Sub sub){
  34.   this.sub = sub;
  35.  }
  36.  @Override
  37.  public void run(){
  38.   sub.operateIMainMethod();
  39.  }
  40. }
  41. public class Run {
  42.  public static void main(String[] args) {
  43.   // TODO Auto-generated method stub
  44.   Sub sub = new Sub();
  45.   MyThread t = new MyThread(sub);
  46.   t.start();
  47.   MyThread t1 = new MyThread(sub);
  48.   t1.start();
  49.  }
  50. }

 

运行结果如下:

 

  从结果可以看出线程Thread-0先访问子类的同步方法operateIMainMethod,输入Thread-0 sub print i=10,然后在还未释放对象锁的情况下重新获得对象锁访问父类的同步方法operateIMainMethod,输出Thread-0 main print i=9,然后进入下一个循环。

  线程Thread-0访问结束释放对象锁后,线程Thread-1开始访问。由于共享同一个对象且i在同步方法operateIMainMethod()外被定义,所以当线程Thread-1访问时i已经为零。

 

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3