这段代码是否有竞争条件?

时间:2016-01-22 20:10:59

标签: java multithreading static java-threads

我只需要用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();

    }

}   

6 个答案:

答案 0 :(得分:6)

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

此外,无法保证跨线程可以看到共享变量的更新,因此一个线程甚至可能看不到其他线程的更新值。

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

++的工作原理如下:Why ++ is not implemented as an atomic operation in Java

答案 1 :(得分:0)

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

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

count在哪里宣布?

答案 2 :(得分:0)

为了具有竞争条件,您需要具有读/写共享内存部分的线程(例如全局/静态变量)。在这里,你的线程没有交互,因此没有竞争条件。此外,您在线程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();
    }

}

答案 3 :(得分:0)

"当两个或多个线程可以访问共享数据并且他们尝试同时更改它时,会出现争用情况。因为线程调度算法可以在任何时间在线程之间交换,所以您不知道线程将尝试访问共享数据的顺序。因此,数据变化的结果取决于线程调度算法,即两个线程都是"赛车"访问/更改数据。" SOURCE = What is a race condition?

注意这部分"数据变化的结果取决于线程调度算法"以及如何在代码中操作变量计数。

答案 4 :(得分:0)

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

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的值。因此,我们不会获得预期值10,而是获得25

答案 5 :(得分:-1)

这是代码:

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();

    }

}