我在java中混淆了内存模型,示例如下代码:
/**
* one thread write request and wait for response
*/
public AbstractPacket writeMessageAndWaitForResp(AbstractPacket packet, int waitTimeoutInSecond) {
if (!(packet instanceof SendToRouter)) {
throw new IllegalArgumentException("this msg can not be sent to router!");
}
int command = packet.getResponseCommand();
AbstractPacket[] slot = new AbstractPacket[]{NullPacket.NULL};
synchronized (("" + this.getFactoryId() + this.getRouterNo() + command).intern()) {// prevent same command request re-entry
command2RespMap.put(command, slot);
synchronized (slot) { // prevent notify before wait
ChannelFuture future = writeMessage(packet);
if (future == null) {
command2RespMap.remove(command);
return null;
}
try {
slot.wait(waitTimeoutInSecond * 1000);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
command2RespMap.remove(command);
}
AbstractPacket result = slot[0]; // get out the result outof slot array
if (result == NullPacket.NULL) {
logger.error("receive sync message timeout!");
return null;
}
return result;
}
/**
* another thread write response and notify the waiter
*/
public void routerResponse(AbstractPacket packet) {
int command = packet.getHeadCommand();
AtomicReference<AbstractPacket> slot = command2RespMap.get(command);
if (slot == null || slot.get() != NullPacket.NULL) {
logger.error("command : {} request not exist !", command);
return;
}
synchronized (slot) {
slot[0] = packet;
slot.notify();
}
}
我的问题是,在第一个函数中,我从插槽变量的synchronized块中获取了索引0中的槽的结果。
这是否意味着slot [0]可能不包含另一个线程中第二个函数设置的值?
非常感谢!答案 0 :(得分:0)
synchronized
关键词,作为记忆障碍,保证了两件事
编译器可能会交换程序中某些语句的顺序。但是,在看到同步块时,块中的任何语句都不会被重新排序或与同步块之外的语句混合。
在块内部,任何变量都将从主存储器中获取它的值,并且将丢弃线程本地副本和/或L2高速缓存/寄存器高速缓存值。在块结束时,块中修改的变量将被写回主存储器,以便所有其他线程读取相同的值。
因此,由于您在synchronized块之外引用slot [0],因此不能保证此引用与您在synchronized块内更新的值一致,也不能保证它是否是本地缓存的线程价值或来自主存。
正如@chrylis提到的那样BTW,你的块非常昂贵,你需要考虑至少移动wait()。