java - 在 Java 中,锁定是否确保读取和写入非 volatile 位置的正确顺序

标签 java multithreading

假设我有一个类的共享对象:

class Shared {
    private int x = 0 ;
    private int y = 0 ;
    private Semaphore s = new Semaphore() ;

    public int readX() {
        s.p() ;
        int x0 = x ;
        s.v() ;
        return x0 ; }

    public void writeX(int x0) {
        s.p() ;
        x = x0 ;
        s.v() ; }

    public int readY() {
        s.p() ;
        int y0 = y ;
        s.v() ;
        return y0 ; }

    public void writeY(int y0) {
        s.p() ;
        y = y0 ;
        s.v() ; } }

这里的 Semaphore 是一个使用同步方法来提供互斥的类。

现在发生以下操作:

  • 线程 0 调用 o.readX() 并发现它为 0。
  • 线程 1 使用 o.writeX(1) 将 1 写入 x,然后将 1 写入 y; o.writeY(1) ;
  • 线程 0 调用 o.readY() 获取 1,然后调用 o.readX()。

线程 0 能否从其缓存中读取并发现 x 为 0?为什么?


编辑

这是信号量类

class Semaphore {
    private boolean available = true ;

    public synchronized void v() {
        available = true ; notifyAll() ; }

    public synchronized void p() {
        while( !available ) try{ wait() ; } catch(InterruptedException e){} 
        available = false ; }
}

最佳答案

根据 JMM,以下序列严格按照发生前关系排序,因此保证了在第 1 步中所做的更改对第 4 步的读者可见:

  1. 写信给x
  2. 退出由监视器 M 保护的同步块(synchronized block)
  3. 进入由监视器M保护的同步块(synchronized block)
  4. 读x

写入变量 happens-before 释放监视器,释放监视器 happens-before 获取相同的监视器和获取监视器 happens-before 从变量读取。

因此,如果 pv 同步,则线程 0 将看到对 x 的更改。

关于java - 在 Java 中,锁定是否确保读取和写入非 volatile 位置的正确顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22069334/

相关文章:

java - 字节码操作安全吗

java - 如何从url加载图片

java - 将 UML 图映射到 Java 代码转换

c# - WPF 中线程的一个非常基本的解释?

c - 嵌套线程创建期间的数据竞争

java - 错误 java.sql.SQLException : Parameter index out of range

java - Spring MVC请求参数自动映射复杂对象

c - 数据记录应用程序、服务器组件 - 单独的线程还是单独的进程?

c# - 从 WinForms 应用程序中的另一个线程访问由 GUI 工作线程创建的按钮

c - 通过 pthread_join() 加入两个 pthread 无法按预期工作