【问题标题】:Does this code have a race condition?这段代码有竞争条件吗?
【发布时间】:2016-01-22 20:10:59
【问题描述】:

我只需要用java线程做一个竞态条件的例子,我写了这段代码,但我不确定它是否有竞态条件。

谁能告诉我下面的代码是否存在竞争条件,以及如何改进或简化它?

(抱歉英语不好)

public class RaceCondition extends Thread{

static int count=0;   //the variable where the race condition need to happen
static int contador1 = 0;    //variables to count
static int contador2 = 0;


static Thread t1 = new Thread(new Runnable() {
    public void run(){

        while(contador1!=20){
        count ++;
        System.out.print(count + " ");
        contador1++;

        }
    }
     });

static Thread t2 = new Thread(new Runnable() {
    public void run(){
        while(contador2!=20){

        int k = 5;
        count += 5*k;
        System.out.print(count + " ");
        contador2 ++;

        }
    }
     });

public static void main(String[] args) {

     t1.start();
     System.out.println(" ");
     t2.start();

    }

}   

【问题讨论】:

  • 代码必须运行才能有竞争条件。我没有看到count 的声明。这段代码能编译吗?
  • @user 如果程序运行,线程将继续运行直到它们完成,因为它们不是守护线程。你在看什么?
  • @user 主线程在主线程完成后会死掉,活线程不会。

标签: java multithreading static java-threads


【解决方案1】:

您确实有竞争条件。 +++= 操作在 Java 中都不是作为原子操作实现的,两个线程在尝试读取和更新计数字段时可能会相互干扰。

此外,无法保证对共享变量的更新在线程间可见,因此一个线程甚至可能看不到另一个线程的更新值。

您可以通过将 count 静态变量设置为 AtomicInteger 来解决这两个问题。使用getAndIncrement 代替++,使用getAndAdd 代替+=

关于为什么++ 会这样工作,请参阅Why ++ is not implemented as an atomic operation in Java

【讨论】:

  • 最后。在众多不正确的答案中找到正确答案。
  • @SergeyA:谢谢 :-) OP 更正了他的代码,其他答案都基于旧版本。
【解决方案2】:

您没有任何竞争条件。线程仅分别访问变量contador1contador2。两个线程都没有修改或读取变量。

t2 甚至有它自己使用的本地k,而不是你标记的k

count 在哪里声明?

【讨论】:

  • 抱歉 k 实际上是计数变量。
【解决方案3】:

“当两个或多个线程可以访问共享数据并尝试同时更改它时,就会发生竞争条件。因为线程调度算法可以随时在线程之间交换,所以你不知道其中的顺序线程将尝试访问共享数据。因此,数据更改的结果取决于线程调度算法,即两个线程都在“竞相”访问/更改数据。 源 = What is a race condition?

请注意这部分“数据更改的结果取决于线程调度算法”以及代码中变量计数的操作方式。

【讨论】:

    【解决方案4】:

    为了有一个竞争条件,你需要有线程来读/写内存的共享部分(例如一个全局/静态变量)。在这里,您的线程不交互,因此没有竞争条件。此外,您在线程 2 代码中重新声明了 k,因此您的全局 k 永远不会被使用。

    试试这个:

    public class RaceCondition extends Thread{
    
        static int k = 0;       //the variable where the race condition need to happen
    
    
        public void run(){
    
            while( k != 20 ){
                k++;
                try{
                    Thread.sleep( 1 );
                }catch( InterruptedException e ){
    
                }
                System.out.print( k + " " );
    
            }
        }
    
    
        public static void main( String[] args ){
    
            RaceCondition t1 = new RaceCondition();
            RaceCondition t2 = new RaceCondition();
            t1.start();
            t2.start();
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      没有。当两个或多个线程访问相同的变量时,就会出现竞争条件,这会导致结果出现问题。例如,

      static int a = 2;
      static int b = 0;
      
      static Thread t1 = new Thread(new Runnable() {
          public void run(){
              if(a == 2) {
                  b = 5 * a;
                  System.out.println(a);
              }
          }
      });
      
      static Thread t2 = new Thread(new Runnable() {
          public void run(){
              a = 5;
          }
      });
      

      这里,考虑一下在 Thread1 刚刚执行了if(a == 2) 之后,Thread2 改变了a = 5 的值。因此,我们将得到25,而不是期望值 10。

      【讨论】:

        【解决方案6】:

        这是代码:

        package RaceCondition;
        
        public class RaceCondition extends Thread {
        
            static int count = 0;
            static int contador1 = 0;
            static int contador2 = 0;
        
            static Thread t1 = new Thread(new Runnable() {
                public void run() {
        
                    while (contador1 != 20) {
                        count++;
                        System.out.print(count + " ");
                        contador1++;
                    }
                    System.out.println("fine t1");
        
                }
            });
        
            static Thread t2 = new Thread(new Runnable() {
                public void run() {
                    while (contador2 != 20) {
                        int k = 5;
        
                        count += 5;
        
                        System.out.print(count + " ");
                        contador2++;
                    }
                    System.out.println("fine t2");
                }
            });
        
            public static void main(String[] args) {
        
                t1.start();
                System.out.println(" ");
        
                t2.start();
        
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-29
          • 1970-01-01
          • 1970-01-01
          • 2014-02-21
          • 1970-01-01
          • 2021-05-16
          相关资源
          最近更新 更多