本帖最后由 凋灵兔子 于 2019-8-4 16:36 编辑
是有用的, 因为 JMM 只是逻辑上存在, 不同线程之间仍然需要 volatile 同步, MESI 协议只是保证万一两个线程运行在不同的 CPU 上时用来同步它们之间的工作内存.
下面是原问题

最近在学 JMM, 有一个问题想不明白, 而且又无法编程来验证.
其实这个问题和 mc 关系不大(也有关系...毕竟写个插件mod也得用多线程嘛), 但是在别的论坛问又没人理我, 所以发到 mcbbs 这种 dalao 云集的地方试试...= =
volatile 的实现是用缓存一致性协议(MESI)来做的(增加汇编指令 "lock" 来立即更新主存中的值). 根据其特性, MESI 是在至少有两个 cpu 核心的电脑上才有意义, 但是即使电脑只有一个核心, 在 java 编程中依然可以使用多线程技术(看上去像并行的串行), 那在这种情况下 volatile 是不是就失去了其对 "可见性" 的意义, 只剩下禁止指令重排的功能了?
被水贴水的不敢发锭了, 没法验证的原因主要是找不到只有一个核心的电脑...
刚才仔细思考了一下, 核心让多个线程交替执行, 上面那个问题其实可以转化为另一个问题: 核心在进行线程交替的时候是否会将寄存器中的值保存回主存? 如果会的话那 volatile 就失去了对可见性的意义. 因为线程切换时会回写到主存, 其他线程看到的永远都是最新的. 相反若直接丢弃寄存器中的数据, 那其他线程看到的还是旧的值. 不加 volatile 让它立即保存就会出现线程安全问题. 在进程切换的时候确实会保存 cpu 现场, 但是线程切换会不会保存寄存器...有木有 dalao 解答一下...
我猜应该是会保存的, 不保存那线程运行的结果都没了那不是白运行了么...但是又不太敢说这么重要一个关键字在单核环境中就没蛋用.
是有用的, 因为 JMM 只是逻辑上存在, 不同线程之间仍然需要 volatile 同步, MESI 协议只是保证万一两个线程运行在不同的 CPU 上时用来同步它们之间的工作内存.

最近在学 JMM, 有一个问题想不明白, 而且又无法编程来验证.
其实这个问题和 mc 关系不大(也有关系...毕竟写个插件mod也得用多线程嘛), 但是在别的论坛问又没人理我, 所以发到 mcbbs 这种 dalao 云集的地方试试...= =
volatile 的实现是用缓存一致性协议(MESI)来做的(增加汇编指令 "lock" 来立即更新主存中的值). 根据其特性, MESI 是在至少有两个 cpu 核心的电脑上才有意义, 但是即使电脑只有一个核心, 在 java 编程中依然可以使用多线程技术(看上去像并行的串行), 那在这种情况下 volatile 是不是就失去了其对 "可见性" 的意义, 只剩下禁止指令重排的功能了?
被水贴水的不敢发锭了, 没法验证的原因主要是找不到只有一个核心的电脑...
刚才仔细思考了一下, 核心让多个线程交替执行, 上面那个问题其实可以转化为另一个问题: 核心在进行线程交替的时候是否会将寄存器中的值保存回主存? 如果会的话那 volatile 就失去了对可见性的意义. 因为线程切换时会回写到主存, 其他线程看到的永远都是最新的. 相反若直接丢弃寄存器中的数据, 那其他线程看到的还是旧的值. 不加 volatile 让它立即保存就会出现线程安全问题. 在进程切换的时候确实会保存 cpu 现场, 但是线程切换会不会保存寄存器...有木有 dalao 解答一下...
我猜应该是会保存的, 不保存那线程运行的结果都没了那不是白运行了么...但是又不太敢说这么重要一个关键字在单核环境中就没蛋用.
个人猜想是将每个线程的栈帧写入主存,而所谓的寄存器的值(也就是 JVM 的 4 个局部变量)也会随着栈帧一起带进去,但是否正确还有待验证