gpt4 book ai didi

java - 线程并发——同步和锁。

转载 作者:行者123 更新时间:2023-12-02 08:02:53 25 4
gpt4 key购买 nike

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 中使用的锁不同的锁上调用。

  • 在上面的示例中,对“sa”对象调用了 wait() 和 notification()。单独调用notify() 和使用对象(即sa.wait() 和sa.notify())调用notify()/wait() 有什么区别?

  • 在 Test 类中,synchronized block 具有 sa 对象的锁,并且 sa 对象是静态的,但在 ZiggyTest2 类中,synchronized block 使用相同的 sa 对象引用,但使用非静态,这有什么关系吗?引用?假设一个是静态的,另一个不是,它们是否仍然使用相同的锁?

最佳答案

当你执行

sa = new String("Done");

您不会更改 sa 引用的字符串的内容。您将一个新的 String 实例(一个新对象)分配给 sa。字符串是不可变的。改变它们的值是不可能的。

这意味着您在 sa (第一个对象:“未完成”)上进行同步,然后将一个新对象分配给 sa (第二个对象:“完成”),并在第二个对象上调用通知。由于您尚未在第二个对象上同步,但在第一个对象上同步,因此您会收到 IllegalMonitorException。仅当您拥有对象的内在锁时,才允许对对象调用通知。这就是为什么锁应该始终是最终的。

调用notify()相当于调用this.notify()。因此,this.notify()sa.notify() 只是在两个不同的对象上调用 notify()。第一个将通知等待 this 的线程,第二个将通知等待 sa 的线程。

变量是否静态并不重要。锁与对象相关联,而不是与其引用相关联。

关于java - 线程并发——同步和锁。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8636457/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com