首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同步块中的java内存模型

同步块中的java内存模型
EN

Stack Overflow用户
提问于 2015-01-05 10:00:55
回答 1查看 119关注 0票数 0

我对java中的内存模型感到困惑,示例如下:

代码语言:javascript
复制
 /**
  * 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();
        }
}

我的问题是,在第一个函数中,我从slot变量上的synchronized块中的索引0中获得了结果。

这是否意味着插槽可能不包含由另一个线程中的第二个函数设置的值?

非常感谢!

EN

回答 1

Stack Overflow用户

发布于 2015-01-05 10:17:47

synchronized关键字作为记忆屏障,可以保证两件事

  1. 编译器可能会交换程序中某些语句的顺序。但是,在看到同步块时,块中的任何语句都不会被重新排序或与同步块外的语句混合。
  2. 在块内,任何变量的值都将从主内存中获取,线程本地副本和/或L2缓存/寄存器缓存的值将被丢弃。在块结束时,在块中修改的变量将被写回到主存中,这样所有其他线程都将读取相同的值。

因此,由于您引用的是同步块外部的插槽,因此不能保证此引用与您在同步块内更新的值一致,也不能保证它是线程本地缓存值还是来自主内存的值。

顺便说一句,正如@chrylis所提到的,你的代码块是非常昂贵的,你至少需要考虑把wait()移出。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27772492

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档