本来我一直以为synchronized是把当前this对象和方法绑定起来锁定方法,实现资源共享中线程安全机制,当方法执行完成之后锁被释放,直到下面的例子产生了疑惑 如果是上述结果的话,那么锁住的不仅仅是当前调用的这个方法,只要是被注明synchronized关键字的所有方法在未运行时就都被锁定了,然而我有编辑下面一个例子,证明了我的想法又是错误的

java 代码
  1. public class A{   
  2.        
  3.     public synchronized void do1() throws Exception{   
  4.         System.out.println("do1 enter");   
  5.         Thread.sleep(2000);   
  6.         System.out.println("do1 end");   
  7.     }   
  8.        
  9.     public synchronized void do2() throws Exception{   
  10.         System.out.println("do2 enter");   
  11.         System.out.println("do2 end");   
  12.     }   
  13.        
  14.     public static void main(String[] args){   
  15.         final A obj=new A();   
  16.         new Thread(){   
  17.             public void run(){   
  18.                 try {   
  19.                     obj.do1();   
  20.                 } catch (Exception e) {   
  21.                     e.printStackTrace();   
  22.                 }   
  23.             }   
  24.         }.start();   
  25.            
  26.         new Thread(){   
  27.             public void run(){   
  28.                 try {   
  29.                     obj.do2();   
  30.                 } catch (Exception e) {   
  31.                     e.printStackTrace();   
  32.                 }   
  33.             }   
  34.         }.start();   
  35.     }   
  36.        
  37. }  

运行结果是

 

do1 enter
do1 end
do2 enter
do2 end

 

 

java 代码
  1.   
  2. public class B {   
  3.   
  4.     public synchronized void fun1(){   
  5.         System.out.println("fun1() is invoked");   
  6.         fun2();   
  7.     }   
  8.     public synchronized void fun2(){   
  9.         System.out.println("fun2() is invoked");   
  10.     }   
  11.     public static void main(String[] args) {   
  12.         B obj=new B();   
  13.         obj.fun1();   
  14.     }   
  15.   
  16. }   

     运行结果是

     fun1() is invoked
      fun2() is invoked

如果采用上一个例子中的经验,那么这个类B应该是在未运行时锁住了该OBJ实例中的两个方法,刚进入fun1()时把当前this对象锁住了,但是应该无法运行fun2(),因为fun2()无法在fun1()没有释放锁的情况下再次获得锁,应该失去了活跃性,造成dead lock,但这里为什么会正常运行了,同步机制到底锁的什么?如果其中两个方法加了synchronized关键字,在多线程环境中能不能同时被调用?请一下

评论
galaxystar 2007-09-10
楼主可以研究下 jdk1.5的 reentrantLock, 以及同步器 abstractQueuedSynchronizer
andy_java 2007-09-09
dennis_zane 写道
andy_java 写道
dennis_zane 写道
第二段代码中,主线程运行fun1(),请求了锁,fun1()中要调用fun2(),仍然是同一个线程内,仅仅是这个锁关联的计数+1,仍然可以获得锁,原因如上所述。
是不是说明了多线程环境中锁的是当前对象下的所有的同步方法,而单线程环境中锁的是当前调用的方法?


要理解这句话:对锁的请求是基于每个线程,而不是每个调用。多线程环境下,某个线程1方法1请求一个锁A,那么其他线程要获得锁A就要等待,线程1中方法1中如果再次请求锁A,锁是可重进入的,且是同一个线程,那么方法1中的请求获得通过,并且锁关联的计数+1,此时其他线程要想获得锁A仍然要等待线程1释放两次锁A了(因为请求了两次,同一个线程内可重复请求)
呵呵,基本明白是怎么回事了,锁是多线程共享的,在多线程中,如果一个线程获得了多线程所共享的对象锁,那么其它线程就不能再占用该锁,只能进入阻塞状态,但是在同一线程内可以多次占用同一个锁,因为同一线程中锁是可以进入的,所以每个持有该锁的方法都可以同时获得该锁,且内部有一个锁的计数器,每获得该锁一次就+1,只有当该计数器清0的时候,其它线程才能获得该锁.
这是不是线程的默认机制?同步块是不是也采用这个机制?请楼上的高手再讲解一下:)
dennis_zane 2007-09-09
andy_java 写道
dennis_zane 写道
第二段代码中,主线程运行fun1(),请求了锁,fun1()中要调用fun2(),仍然是同一个线程内,仅仅是这个锁关联的计数+1,仍然可以获得锁,原因如上所述。
是不是说明了多线程环境中锁的是当前对象下的所有的同步方法,而单线程环境中锁的是当前调用的方法?


要理解这句话:对锁的请求是基于每个线程,而不是每个调用。多线程环境下,某个线程1方法1请求一个锁A,那么其他线程要获得锁A就要等待,线程1中方法1中如果再次请求锁A,锁是可重进入的,且是同一个线程,那么方法1中的请求获得通过,并且锁关联的计数+1,此时其他线程要想获得锁A仍然要等待线程1释放两次锁A了(因为请求了两次,同一个线程内可重复请求)
andy_java 2007-09-09
dennis_zane 写道
第二段代码中,主线程运行fun1(),请求了锁,fun1()中要调用fun2(),仍然是同一个线程内,仅仅是这个锁关联的计数+1,仍然可以获得锁,原因如上所述。
是不是说明了多线程环境中锁的是当前对象下的所有的同步方法,而单线程环境中锁的是当前调用的方法?
dennis_zane 2007-09-09
第二段代码中,主线程运行fun1(),请求了锁,fun1()中要调用fun2(),仍然是同一个线程内,仅仅是这个锁关联的计数+1,仍然可以获得锁,原因如上所述。
dennis_zane 2007-09-09
很简单,因为锁是可重进入的(Reentrancy),对锁的请求是基于每个线程,而不是每个调用。
andy_java 2007-09-09

"如果是上述结果的话,那么锁住的不仅仅是当前调用的这个方法,只要是被注明synchronized关键字的所有方法在未运行时就都被锁定了,然而我有编辑下面一个例子,证明了我的想法又是错误的"

这段话是用来解释第一段代码的

发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

andy_java
搜索本博客
博客分类
最近加入圈子
最新评论