【发布时间】:2018-03-16 21:22:37
【问题描述】:
我在 IBM - developerworks 上偶然发现了 this article,他们发布的代码让我提出了一些问题:
为什么局部变量
Map的构建被包裹在synchronized块中?请注意,他们隐含地说只有一个producer线程。实际上,为什么这个 sn-p 需要
synchronized块呢?volatile变量应该足以完成这项工作,因为新创建的地图只有在填满后才会发布。锁对象上只有一个线程
synchronizing有什么意义?
文章提到:
清单 1 中的同步块和 volatile 关键字是必需的,因为在对 currentMap 的写入和从 currentMap 的读取之间不存在发生前的关系。因此,如果未使用同步块和 volatile 关键字,读取线程可能会看到垃圾。
并且代码中的注释说:
由于 Java 内存模型,这必须同步
我觉得我正在处理超出我理解范围的多线程概念;我希望有更专业的人为我指明正确的方向。
这是从文章中摘录的sn-p:
static volatile Map currentMap = null; // this must be volatile
static Object lockbox = new Object();
public static void buildNewMap() { // this is called by the producer
Map newMap = new HashMap(); // when the data needs to be updated
synchronized (lockbox) { // this must be synchronized because
// of the Java memory model
// .. do stuff to put things in newMap
newMap.put(....);
newMap.put(....);
}
/* After the above synchronization block, everything that is in the HashMap is
visible outside this thread */
/* Now make the updated set of values available to the consumer threads.
As long as this write operation can complete without being interrupted,
and is guaranteed to be written to shared memory, and the consumer can
live with the out of date information temporarily, this should work fine */
currentMap = newMap;
}
public static Object getFromCurrentMap(Object key) {
Map m = null;
Object result = null;
m = currentMap; // no locking around this is required
if (m != null) { // should only be null during initialization
Object result = m.get(key); // get on a HashMap is not synchronized
// Do any additional processing needed using the result
}
return(result);
}
【问题讨论】:
-
在这种情况下,单线程是生产者这一事实并不是很重要。当消费者线程尝试读取而生产者写入时,就会出现问题。
-
@NiVeR 感谢您的评论。这并不能解释
synchronized块吗?不管那个区块有没有,都会出现新创建的地图发布而其他人阅读的情况……或者不是吗?一次只有一个线程访问地图一次将要求消费者也有一个sync块,或任何其他锁定机制...... -
@Marko
volatile应该解决这个问题。
标签: java multithreading synchronized volatile producer-consumer