Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多线程异步(不一致)访问java中的字段会发生什么情况?_Java_Multithreading_Thread Safety - Fatal编程技术网

多线程异步(不一致)访问java中的字段会发生什么情况?

多线程异步(不一致)访问java中的字段会发生什么情况?,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我认为我对使用synchronized关键字来防止java中线程之间的不一致有着相当坚定的理解,但我不完全理解如果不使用该关键字会发生什么 例如,假设我有一个由两个线程访问/修改的字段: private String sharedString = ""; class OneThread extends Thread { private Boolean mRunning = false; public OneThread() {} public synchronized set

我认为我对使用
synchronized
关键字来防止java中线程之间的不一致有着相当坚定的理解,但我不完全理解如果不使用该关键字会发生什么

例如,假设我有一个由两个线程访问/修改的字段:

private String sharedString = "";

class OneThread extends Thread {

  private Boolean mRunning = false;

  public OneThread() {}

  public synchronized setRunning(Boolean b) {
    mRunning = b;
  }

  @Override
  public void run() {
    while (mRunning) {
      // read or write to shared string
      sharedString = "text from thread 1";
      System.out.println("String seen from thread 1: " + sharedString);
      super.run();
    }
  }
}

class AnotherThread extends Thread {

  private Boolean mRunning = false;

  public AnotherThread() {}

  public synchronized setRunning(Boolean b) {
    mRunning = b;
  }

  @Override
  public void run() {
    while (mRunning) {
      // read or write to shared string
      sharedString = "text from thread 2";
      System.out.println("String seen from thread 2: " + sharedString);
      super.run();
    }
  }
}
由于这两个线程都在访问和修改字段
sharedString
,而没有使用synchronized关键字,因此我预计会出现不一致的情况。我想知道的是实际发生了什么。在调试过程中,我仔细检查了这两个线程,发现即使其中一个线程暂停,它的状态也可能是“粘滞的”

对于上面的示例,假设两个线程都在调试器中暂停。如果我单步执行其中一个线程,而让另一个线程暂停,我希望它会像单线程应用程序一样运行。然而,很多时候,在修改字段之后,访问字段的下一行检索到“错误”的值(与刚修改的值不一致)

我知道这个代码不好。。但我提出这个问题是因为我希望有人能提供一个答案,让我们了解当多线程应用程序实现不佳时虚拟机中实际发生的情况。尝试修改字段失败的线程是否有任何影响


如果在糟糕地实现了多线程代码之后,我们只是处于“未定义”行为的领域,而了解这种行为没有任何价值,那么我同意。。只是一个多线程的noob试图理解我在调试器中观察到的情况。

这是由于Java中跨线程同步的另一个关键功能:防止数据过时。作为Java内存模型的一部分,Java线程可以缓存共享数据的值。除非共享的可变数据在同步块中被访问或被标记为易失性数据,否则不能保证一个线程会看到另一个线程所做的更新。有关更多信息,请参阅。

这是由于Java中跨线程同步的另一个关键功能:防止数据过时。作为Java内存模型的一部分,Java线程可以缓存共享数据的值。除非共享的可变数据在同步块中被访问或被标记为易失性数据,否则不能保证一个线程会看到另一个线程所做的更新。有关更多信息,请参阅。

如果没有其他线程可以更改共享值,则打印输出实际上不可能“错误”(如果只有两个线程,并且其中一个线程肯定已暂停,则情况就是如此)。您是否可以碰巧提供“启动”这两个线程(即主线程)的代码?

如果没有其他线程可以更改共享值,那么打印输出就不会“错误”(如果只有两个线程,并且其中一个线程肯定已暂停,则情况就是如此)。你能提供“启动”这两个线程(即你的主线程)的代码吗?

“如果在糟糕地实现多线程代码之后,我们只是处于“未定义”行为的领域”=>是的,这是一个很好的近似现实。“如果在糟糕地实现多线程代码之后,我们只是处于“未定义”行为的领域”=>是的,这是一个很好的现实近似值。每线程缓存解释了我的观察结果。非常感谢您提供的信息和链接,这非常有用。每线程缓存解释了我的观察结果。非常感谢您提供了非常有用的信息和链接。我没有运行这段代码,但每个线程的开头都是这样的:
OneThread OneThread=new OneThread();oneThread.setRunning(true);oneThread.start()用于每个线程。我相当肯定laz的回答解释了我的观察结果。如果一个线程被暂停,我不认为这是可能的。即使代码和数据没有正确同步,底线是如果没有其他线程在运行,您分配一个值,然后立即读取该值,它不可能发生更改。但如果你下定决心了…我的观察误导了我。假设两个线程都暂停了:第一个线程刚好在字段修改之前,第二个线程刚好在字段修改之后(但在读取之前)。在第一个线程上单步执行修改语句,然后在读取第二个线程时,我希望读取返回的值正好由第一个线程更新。但是由于该字段没有声明为volatile,所以每个线程都有自己的缓存副本,而第二个线程的缓存数据是过时的(在我的noobness中称之为“sticky”)。好的。谢谢你的澄清。我想我也学到了一些东西:)。谢谢你回来回答。我没有运行这个确切的代码,但是每个线程的开始都是这样的:
onethreadonethread=newonethread();oneThread.setRunning(true);oneThread.start()用于每个线程。我相当肯定laz的回答解释了我的观察结果。如果一个线程被暂停,我不认为这是可能的。即使代码和数据没有正确同步,底线是如果没有其他线程在运行,您分配一个值,然后立即读取该值,它不可能发生更改。但如果你下定决心了…我的观察误导了我。假设两个线程都暂停了:第一个线程刚好在字段修改之前,第二个线程刚好在字段修改之后(但在读取之前)。在第一个线程上单步执行修改语句,然后在读取第二个线程时,我希望读取返回的值正好由第一个线程更新。但是由于该字段没有声明为volatile,因此每个线程都有自己的缓存副本,而第二个线程的缓存数据是过时的(在我的noobness中是什么