同步块中的java内存模型

时间:2015-01-05 02:00:55

标签: java concurrency concurrent-programming

我在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]可能不包含另一个线程中第二个函数设置的值?

非常感谢!

1 个答案:

答案 0 :(得分:0)

synchronized关键词,作为记忆障碍,保证了两件事

  1. 编译器可能会交换程序中某些语句的顺序。但是,在看到同步块时,块中的任何语句都不会被重新排序或与同步块之外的语句混合。

  2. 在块内部,任何变量都将从主存储器中获取它的值,并且将丢弃线程本地副本和/或L2高速缓存/寄存器高速缓存值。在块结束时,块中修改的变量将被写回主存储器,以便所有其他线程读取相同的值。

  3. 因此,由于您在synchronized块之外引用slot [0],因此不能保证此引用与您在synchronized块内更新的值一致,也不能保证它是否是本地缓存的线程价值或来自主存。

    正如@chrylis提到的那样BTW,你的块非常昂贵,你需要考虑至少移动wait()。