Java 寻找竞争条件

Java 寻找竞争条件,java,multithreading,conditional-statements,Java,Multithreading,Conditional Statements,有人能解释一下这段代码中的竞争条件在哪里吗。我的讲师设定的,我还不完全理解如何发现它们,或者说为什么给出的结果会发生 public class SlowRace { public static void main(String args []) throws Exception { MyThread.count = 0 ; MyThread thread1 = new MyThread() ; thread1.name

有人能解释一下这段代码中的竞争条件在哪里吗。我的讲师设定的,我还不完全理解如何发现它们,或者说为什么给出的结果会发生

public class SlowRace {

      public static void main(String args []) throws Exception {

          MyThread.count = 0 ;

          MyThread thread1 = new MyThread() ;
          thread1.name = "A" ;

          MyThread thread2 = new MyThread() ;
          thread2.name = "B" ;

          thread1.start() ;
          thread2.start() ;

          thread2.join() ;
          thread1.join() ;

          System.out.println("MyThread.count = " + MyThread.count) ;
      }
  }

  class MyThread extends Thread {

      volatile static int count ;

      String name ;

      public void run() {

          for(int i = 0 ; i < 10 ; i++) {
              delay() ;
              int x = count ;
              System.out.println("Thread " + name + " read " + x) ;
              delay() ;
              count = x + 1;
              System.out.println("Thread " + name + " wrote " + (x + 1)) ;
          }
      }

      static void delay() {

          int delay = (int) (1000000000 * Math.random()) ;
          for(int i = 0 ; i < delay ; i++) {}
      }
  } 
嘿,伙计们,有人能解释一下这段代码中的种族条件吗

比赛在以下两条线之间进行:

          int x = count ;
          ...
          count = x + 1;
一个线程获取该值,但在第一个线程使用递增的值更新该值之前,另一个线程可以获取相同的值。这就是比赛

  • 线程1获取
    count
    的值,并将其存储在
    x
    x
    is(比如说10)
  • 同时,线程2还获取
    count
    的值,并将其存储在
    x
    x
    is(比如说10)
  • 线程1将
    x
    递增为
    11
    ,并将其存储回
    count
  • 线程2将其
    x
    的副本增量为
    11
    ,并将其存储回
    count
    ——这将覆盖线程1的增量
  • 因此,
    count
    不是12,而是一个增量已经丢失,它将是11

    练习是要指出增量不是原子的。实际上,
    delay()
    是不必要的<代码>计数++< /代码>也将演示这个问题,因为它不是原子(get /增量/ set),线程可以在3个操作的中间被中断。
    使此代码复杂化的一件事是,
    System.out.println(…)
    是同步的,因此控制台输出将更改程序的计时。

    您告诉编译器将信息存储在内存而不是缓存中

    volatile static int count ;
    
    2个线程同时执行此运行

      public void run() {
    
          for(int i = 0 ; i < 10 ; i++) {
              delay() ;
              int x = count ;
              System.out.println("Thread " + name + " read " + x) ;
              delay() ;
              count = x + 1;
              System.out.println("Thread " + name + " wrote " + (x + 1)) ;
          }
      }
    

    此逻辑是线程不安全的,因为对MyThread类中的静态变量count进行了不受保护的更新。

    主线程将在启动线程1和线程2后连接它们,并等待它们完成。但是,同时运行线程(Thread1、Thread2)和不吉利的计时可能会导致更新变量“count”与相同的值一起。

    请展开?'static int count'不要再说了:)@rob1994我已经在一个真实的答案上做了。如果你想参考,他们会在Java教程中解释这一点:那么你将如何使用锁变量来解决这个问题?@rob1994如果你有一个专用于锁的最终对象,只要把
    synchronized(lock){//code}
    放在读和写的周围,你就需要在我引用的行周围加锁
    synchronized(lockObject){int x=count;count=x+1;}
    。参考是在我发布的最后一个链接之后的两个步骤。没有竞相进入for块。价值观的阅读和书写之间存在着一场竞赛。
      public void run() {
    
          for(int i = 0 ; i < 10 ; i++) {
              delay() ;
              int x = count ;
              System.out.println("Thread " + name + " read " + x) ;
              delay() ;
              count = x + 1;
              System.out.println("Thread " + name + " wrote " + (x + 1)) ;
          }
      }
    
    count = 0;
    Thread1(int x = count); //x = 0;
    Thread1(delay)
    Thread2(int x = count); //x = 0;
    Thread2(delay)
    Thread1(count = x + 1); //count = 1;
    Thread2(count = x + 1); //count = 1; //While it has to be 2.