线程并发——同步和锁。
import java.util.*;
import java.io.*;
import java.util.regex.*;
class ZiggyTest2 extends Thread{
String sa;
public ZiggyTest2(String sa){
this.sa = sa;
}
public void run(){
synchronized(sa){
while(!sa.equals("Done")){
try{
sa.wait();
}catch(InterruptedException is){System.out.println("IE Exception");}
}
}
System.out.println(sa);
}
}
class Test{
private static String sa = new String("Not Done");
public static void main(String[] args){
Thread t1 = new ZiggyTest2(sa);
t1.start();
synchronized(sa){
sa = new String("Done");
sa.notify();
}
}
}
当我运行上述程序时,出现以下异常:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at Test.main(ZiggyTest2.java:35)
几个问题:
为什么会出现 IllegalMonitorStateException?因为 Test.sa 被分配给一个新的 String 对象,所以我期望 ZiggyTest2 线程无限期地等待,因为 sa.notify() 将在与 ZiggyTest2 中使用的锁不同的锁上调用。
在上面的例子中,wait() &在“sa”对象上调用notify()。单独调用notify() 和使用对象(即sa.wait() 和sa.notify())调用notify()/wait() 有什么区别?
在 Test 类中,synchronized 块具有 sa 对象的锁,并且 sa 对象是静态的,但在 ZiggyTest2 类中,synchronized 块使用相同的 sa 对象引用,但使用非静态引用,这有关系吗?假设一个是静态的,另一个不是,它们是否仍然使用相同的锁?
import java.util.*;
import java.io.*;
import java.util.regex.*;
class ZiggyTest2 extends Thread{
String sa;
public ZiggyTest2(String sa){
this.sa = sa;
}
public void run(){
synchronized(sa){
while(!sa.equals("Done")){
try{
sa.wait();
}catch(InterruptedException is){System.out.println("IE Exception");}
}
}
System.out.println(sa);
}
}
class Test{
private static String sa = new String("Not Done");
public static void main(String[] args){
Thread t1 = new ZiggyTest2(sa);
t1.start();
synchronized(sa){
sa = new String("Done");
sa.notify();
}
}
}
When i run the above program i get the following exception:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at Test.main(ZiggyTest2.java:35)
A couple of questions:
Why the IllegalMonitorStateException? Because Test.sa is assigned to a new String object, i was expecting the ZiggyTest2 thread to wait indefinately because sa.notify() will be called on a different lock than the one used in ZiggyTest2.
In the above example, wait() & notify() are called on the "sa" object. What is the difference in say calling notify() on its own and calling notify()/wait() using an object i.e. sa.wait() and sa.notify()?
Does it matter that in the Test class the synchronised block has the lock for the sa object and the sa object is static but in the ZiggyTest2 class, the synchronised block uses the same sa object reference but using a non static reference? Given that one is static and the other is not, will they both still be using the same lock?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您执行时,
您不会更改
sa
引用的字符串内容。您将一个新的 String 实例(一个新对象)分配给sa
。字符串是不可变的。改变它们的价值是不可能的。这意味着您在 sa (第一个对象:“未完成”)上进行同步,然后将一个新对象分配给 sa (第二个对象:“完成”),并在第二个对象上调用通知。由于您尚未同步第二个对象,但在第一个对象上同步,因此您会收到 IllegalMonitorException。仅当您拥有对象的内在锁时,才允许对对象调用通知。这就是为什么锁应该始终是最终的。
调用notify()相当于调用this.notify()。因此,
this.notify()
和sa.notify()
只是在两个不同的对象上调用notify()
。第一个将通知等待this
的线程,第二个将通知等待sa
的线程。变量是否静态并不重要。锁与对象相关联,而不是与其引用相关联。
When you execute
you don't change the content of the String references by
sa
. You assign a new String instance (a new object) tosa
. Strings are immutable. It's impossible to change their value.This means that you synchronize on sa (first object : "Not Done"), then assign a new object to sa (second object : "Done"), and call notify on this second object. Since you haven't synchronized on the second object, but on the first one, you get an IllegalMonitorException. Calling notify on an object is only allowed if you own he intrinsic lock on the object. That's why a lock should always be final.
Calling notify() is equivalent to calling this.notify(). So
this.notify()
andsa.notify()
are just callingnotify()
on two different objects. The first one will notify a thread waiting onthis
, and the second one will notify a thread waiting onsa
.The fact that a variable is static or not does not matter. The lock is associated to the object, not to its reference.