gpt4 book ai didi

java - 通过在运行时更改监视器,两个线程进入同步块(synchronized block)

转载 作者:行者123 更新时间:2023-12-01 09:03:46 26 4
gpt4 key购买 nike

注意:尽管下面的场景无效,违反了同步块(synchronized block)的概念,但我仍然试图知道它是如何工作的

创建了两个线程,两个线程都尝试执行相同的临界区,令人惊讶的是,即使通过更改监视器,两个线程都进入了临界区。

public class MultiThreadTest {
final static ConcurrentHashMap<String,Object> objMap = new ConcurrentHashMap<String, Object>();

public static void main(String[] args) {
Thread t1 = new Thread(new MyThread(objMap,"1","T1"));
Thread t2 = new Thread(new MyThread(objMap,"1","T2"));
t1.start();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(MultiThreadTest.class.getName()).log(Level.SEVERE, null, ex);
}
t2.start();
}
}

class MyThread implements Runnable{

private final ConcurrentHashMap<String,Object> objMap;

private final String id;

private final String name;

public MyThread(ConcurrentHashMap<String,Object> objMap, String id, String name){
this.objMap = objMap;
this.id =id;
this.name = name;
}

@Override
public void run() {
Object monitor = getMonitor(id);
synchronized(monitor){
System.out.println("Thread Entered Critica section is:"+id+" and name is:"+name);

try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex);
}

System.out.println("Thread Exiting Critical section is:"+id+" and name is:"+name);

}

}

private Object getMonitor(String id){
if(objMap.contains(id)){
return objMap.get(id);
}else{
objMap.put(id,new Object());
return objMap.get(id);
}
}

}

下面是输出:

Thread Entered Critica section is:1 and name is:T1
Thread Entered Critica section is:1 and name is:T2
Thread Exiting Critical section is:1 and name is:T1
Thread Exiting Critical section is:1 and name is:T2

即使监视器更改,似乎两个线程都会进入。

感谢任何帮助..

最佳答案

正如我在评论中提到的,您的 getMonitor 方法是一个很大的竞争条件,因为您没有在 map 对象上同步,因此在检查 key 是否存在的时间和检查 key 是否存在的时间之间你放入一个新对象,其他线程也可以做同样的事情。

但是,由于您在启动第二个线程之前等待一秒钟,因此这不是这里的问题。

问题是您正在使用 ConcurrentHashMap.contains(Object) 方法,该方法检查是否存在,而不是> 如您所愿地存在。您需要将方法更改为:

private Object getMonitor(String id){
synchronized (objMap) {
if (objMap.containsKey(id)) { // <---- containsKey(...), not contains(...)
return objMap.get(id);
} else {
objMap.put(id, new Object());
return objMap.get(id);
}
}
}

此外,您可以通过实际检查您锁定的监视器来避免得出您的监视器被不同线程锁定两次的错误结论:

System.out.println(
"Thread Entered Critica section is:" + id + " and name is:"
+ name + " and monitor is: " + monitor);

关于java - 通过在运行时更改监视器,两个线程进入同步块(synchronized block),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41455629/

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