简体   繁体   English

为什么同步的getter像volatile一样工作?

[英]Why a synchronized getter work like a volatile read?

This program does not terminate! 该程序不会终止!

public class Main extends Thread {
  private int i = 0;
  private int getI() {return i; }
  private void setI(int j) {i = j; }

  public static void main(String[] args) throws InterruptedException {
    Main main = new Main();
    main.start();

    Thread.sleep(1000);
    main.setI(10);
  }

  public void run() {
    System.out.println("Awaiting...");
    while (getI() == 0) ;
    System.out.println("Done!");
  } 
}

I understand this happens because the CPU core running the Awaiting loop always sees the cached copy of i and misses the update. 我明白这是因为运行Awaiting循环的CPU核心总是看到i的缓存副本并且错过了更新。

I also understand that if I make volatile private int i = 0; 我也明白,如果我使用volatile private int i = 0; then the while (getI()... will behave [1] as if every time it is consulting the main memory - so it will see the updated value and my program will terminate. 然后while (getI()...表现为[1]就像每次咨询主内存一样 - 所以它会看到更新的值,我的程序将终止。

My question is: If I make 我的问题是:如果我做的话

synchronized private int getI() {return i; }

It surprisingly works!! 它令人惊讶地工作! The program terminates. 该计划终止。

I understand that synchronized is used in preventing two different threads from simultaneously entering a method - but here is only one thread that ever enters getI() . 我知道synchronized用于防止两个不同的线程同时进入一个方法 - 但这里只有一个线程进入getI() So what sorcery is this? 这是什么巫术呢?

Edit 1 编辑1

This (synchronization) guarantees that changes to the state of the object are visible to all threads 此(同步)保证对所有线程都可以看到对象状态的更改

So rather than directly having the private state field i , I made following changes: 因此,而不是直接具有私有状态字段i ,我做了以下变化:

In place of private int i = 0; 代替private int i = 0; I did private Data data = new Data(); 我做了private Data data = new Data(); , i = j changed to data.i = j and return i changed to return data.i i = j更改为data.i = jreturn i更改为return data.i

Now the getI and setI methods are not doing anything to the state of the object in which they are defined (and may be synchronized). 现在, getIsetI方法没有对定义它们的对象的状态做任何事情(并且可能是同步的)。 Even now using the synchronized keyword is causing the program to terminate! 即使现在使用synchronized关键字也会导致程序终止! The fun is in knowing that the object whose state is actually changing ( Data ) has no synchronization or anything built into it. 有趣的是知道状态实际发生变化的对象( Data )没有同步或内置任何内容。 Then why? 那么为什么?


[1] It will probably just behave as that, what actually, really happens is unclear to me [1]它可能只是表现为是,究竟是什么,真正发生的是我不清楚

It is just coincidence or platform dependent or specific JVM dependent, it is not guaranteed by JLS. 它只是巧合或平台依赖或特定的JVM依赖,它不受JLS保证。 So, do not depend on it. 所以,不要依赖它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM