()使当前线程出于“不可运行”状态,和 sleep ()不同的是 wait 是 object 的 方法而不是 thread。调用 object.wait ()时,线程先要获取这个对象的对象锁,当前线 程必须在锁对象保持同步,把当前线程添加到等待队列中,随后另一线程可以同步同一 个对象锁来调用 object.notify (),这样将唤醒原来等待中的线程,然后释放该锁。基本 上 wait ()/notify ()与 sleep ()/interrupt ()类似,只是前者需要获取对象锁。 7.在静态方法上使用同步时会发生什么事? 同步静态方法时会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时, 线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不 像实例方法,因为多个线程可以同时访问不同实例同步实例方法。 8.当一个同步方法已经执行,线程能够调用对象上的非同步实例方法吗? 可以,一个非同步方法总是可以被调用而不会有任何
问题。实际上,Java 没有为非同 步方法做任何检查,锁对象仅仅在同步方法或者同步代码块中检查。如果一个方法没有 声明为同步,即使你在使用共享数据 Java 照样会调用,而不会做检查是否安全,所以 在这种情况下要特别小心。一个方法是否声明为同步取决于临界区访问(critial section access),如果方法不访问临界区(共享资源或者数据结构)就没必要声明为同步的。 下面有一个示例说明: Common 类有两个方法 synchronizedMethod1()和 method1(), MyThread 类在独立的线程中调用这两个方法。 1. public class Common { 2. 3. public synchronized void synchronizedMethod1() { 4. System.out.println ("synchronizedMethod1 called"); 5. try { 6. Thread.sleep (1000); 7.
} catch (InterruptedException e) { 8. e.printStackTrace (); 9. } 10. System.out.println ("synchronizedMethod1 done");
11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
} public void method1() { System.out.println ("Method 1 called"); try { Thread.sleep (1000); } catch (InterruptedException e) { e.printStackTrace (); } System.out.println ("Method 1 done"); } }
1. public class MyThread extends Thread { 2. private int id = 0; 3. private Common common; 4. 5. public MyThread (String name, int no, Common object) { 6. super(name); 7. common = object; 8. id = no; 9. } 10. 11. 12. public void run () { System.out.println ("Running Thread" + this.getNa
me ()); 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. try { if (id == 0) { common.synchronizedMethod1(); } else { common.method1(); } } catch (Exception e) { e.printStackTrace (); } }
23. 24. 25. 26. public static void main (String[] args) { Common c = new Common (); MyThread t1 = new MyThread ("MyThread-1", 0, c);
27.
MyThread t2 = new MyThread ("MyThread-2", 1, c);
28. 29. 30. 31.
t1.start (); t2.start (); } }
这里是程序的输出: 1. Running ThreadMyThread-1 2. synchronizedMethod1 called 3. Running ThreadMyThread-2 4. Method 1 called 5. synchronizedMethod1 done 6. Method 1 done
结果表明即使 synchronizedMethod1()方法执行了,method1()也会被调用。 9.在一个对象上两个线程可以调用两个不同的同步实例方法吗? 不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只有执行完 该方法释放对象锁后才能执行其它同步方法。看下面代码示例非常清晰:Common 类 有 synchronizedMethod1()和 synchronizedMethod2()方法,MyThread 调用这两个方 法。 1. public class Common { 2. public synchronized void synchronizedMethod1() { 3. System.out.println ("synchronizedMethod1 called"); 4. try { 5. Thread.sleep (1000);
6. } catch (InterruptedException e) { 7. e.printStackTrace (); 8. } 9. System.ou