Java 无法模拟使用volatile字段修改器

Java 无法模拟使用volatile字段修改器,java,multithreading,Java,Multithreading,在下面的例子中 private Integer a = 10; private Integer c = -10; private int b = -10; public void acquire(){ synchronized(a){ print("acquire()"); try{ b = -12;

在下面的例子中

    private Integer a = 10;
    private Integer c = -10;
    private int b = -10;

    public void acquire(){
        synchronized(a){
            print("acquire()");
            try{                    
                b = -12;
                //Thread.sleep(5000);
                a.wait(5000);
                print("acquire : "+b);
                print("I have awoken");
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        print("Leaving acquire()");
    }


    public void modify(int n){
        print("Entered in modfy");
        synchronized(a){
            try{                    
                b = -15;
                //a.wait(5000);
                Thread.sleep(5000);
                print("modfy : "+b);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
线程A正在调用acquire(),线程B正在调用modify()

一个线程更改的b值对另一个线程可见

  • 线程A:b=-12;等待
  • 线程B:B=-15;印刷品b;出口
  • 线程A:打印b ie-15的新值

  • 如何用上述示例模拟volatile的需求,然后在上述示例中使用volatile。

    如果您只是想模拟volatile的需求,只需执行以下操作:

    volatile int x = 10;
    public void acquire()
    {
         x = 15;   
         print("acquire()");
    }
    
    public void modify(int n)
    {
         print("Entered in modfy");
         x = -15;
    }
    
    //Let threadA call acquire() and threadB call modify()Then print x and see (there should not be any race conditions)
    
    如果您想让它更有趣,请添加更多的线程和方法,并尝试访问
    x

    我这里有一个示例

    你可能会发现的问题有:

    • 虽然
      volatile
      提供了一些内存一致性保证,但不使用volatile并不保证您会看到问题
    • 在Sun/Oracle/OpenJDK JVM中,这个问题似乎不会发生,直到代码得到优化,即运行10000次之后
    • 这通常是一个微妙的比赛条件,即使是微小的变化也可能意味着你看不到问题
    根据“实践中的并发性-手册”,volatile应仅用于变量类型(布尔型)。 如果新状态不依赖于变量的旧状态,则应使用Volatile

    volatile boolean flag=true

    while(旗帜){ ..//做点什么

    }


    当标志变量可以被其他线程修改时,会通知原始线程,因为标志被标记为volatile。否则,循环可能会永远消失。

    本帖前面的问题是:即使你穿过街道时没有朝两边看,也不一定会被车撞到。没有一种方法一定会失败,规则不是这样的。(就像不看就没法过马路一样,你肯定会被车撞到。)@Gray,这不是作业。我只是想在一天内澄清多线程的所有概念。@articlestack我建议,即使有十年的多线程编程经验,您仍将学习。。)@彼得拉维是真的。但至少在某种程度上,这是一个清晰的概念。让我回答其他问题,看看我学了多少。如果这么简单,也许你可以提供一个完整的例子。;)@彼得拉维:我在这里感觉到了讽刺:)。在编写带有套接字的多线程Java程序时,我使用了volatile。我会有一个公共令牌(
    volatile int array
    ),多个线程会更新它。我想这可能是同样的道理。如果不是,请详细说明。我怀疑这并不像你建议的那么简单,但我很高兴被证明是错的。