java - 处理后续网络请求的线程是否可以保证看到在先前请求期间写入的 volatile 变量的值?
问题描述
我有这个关于 Java 内存模型的理论问题。假设我在下面的类中有一个带有这两个请求处理程序的服务器:
class MyHandlers {
volatile int someFlag = 0;
String handleFirstRequest() {
someFlag = 1;
return "Hello!";
}
String handleSecondRequest() {
return "value of someFlag: " + someFlag;
}
}
我也有一个客户。我的客户端发送一个触发执行handleFirstRequest 的网络请求。客户端等待直到请求完成。一旦第一个请求完成,客户端发送触发 handleSecondRequest 的第二个请求。
问题: Java 内存模型如何防止对第二个请求的响应"value of someFlag: 0"
?
注意:我知道,在实践中,处理第二个响应的线程将始终someFlag
显示为 1。
如果我正确读取了 JMM,则有一个同步顺序,即总顺序,someFlag = 1
在我的示例中,它将对 volatile 读取和 volatile 写入 ( ) 进行排序。如果读取在写入之后,则读取将看到写入。是否有可能出现写入在读取之后的情况?在这种情况下,写入不会与读取同步,并且在写入和读取之间不会存在发生之前的关系。这将导致处理第二个请求的线程显示someFlag
为 0。我的理解哪里出错了?
其他想法(2020 年 3 月 2 日): JMM 没有提到时间的概念。同步动作是根据同步顺序排序的,但 JMM 中没有任何内容说同步顺序与按时间排序的动作顺序相同。这表明 Java 实现可能会在写入someFlag
之前排序读取,即使根据时钟读取发生在写入之后。似乎 JMM 只保证如果volatile 读取是在 volatile 写入之后排序的,那么在 volatile 写入之前的写入对于 volatile 读取之后的读取是可见的。
解决方案
如果第一个请求完成,则表示该请求someFlag = 1
已被某个线程执行。此时,someFlag 的值保证对执行读取的任何其他线程可见。因此,当第二个请求到来时,您可以确定它会看到值 1。
推荐阅读
- c# - 通过 SetActive() 在 Unity 中隐藏对象
- python - 从空间数据创建二维数组
- python - Pandas groupby 计算天数
- c++ - 共享内存崩溃安全吗?
- vba - VBA代码根据当前日期打开名称中带有日期的文件
- python - Python 在文件中找到不存在的字符,用非预期字符替换(非英文字符的编码问题)
- c# - ASP.NET Core 中的 WebViewPage.InitializePage() 等价物是什么?
- powershell - 遍历数组并获取所有用户的单元格
- python - DataFrame 来自现有列的新列
- firebase - 如何更新存储在firestore中的发布者信息,以及使用flutter应用程序