如何使这个Java代码正常运行?[多线程,竞争条件]

Fix*_*xee 3 java multithreading race-condition

我从学生那里得到了这个代码,由于涉及x++和的竞争条件,它无法正常工作x--.他补充synchronizedrun()方法试图摆脱这个错误,但显然这只是排除线程进入run()了对同一对象(这是从来没有摆在首位的问题),但并不妨碍独立的对象修改同一静态变量x在同一时间.

public class DataRace implements Runnable {
  static volatile int x;

  public synchronized void run() {
    for (int i = 0; i < 10000; i++) {
          x++;
          x--;
    }
  }

  public static void main(String[] args) throws Exception {
    Thread [] threads = new Thread[100];

    for (int i = 0; i < threads.length; i++)
        threads[i] = new Thread(new DataRace());
    for (int i = 0; i < threads.length; i++)
        threads[i].start();
    for (int i = 0; i < threads.length; i++)
        threads[i].join();

    System.out.println(x); // x not always 0!
  }
}
Run Code Online (Sandbox Code Playgroud)

既然我们无法同步上x(因为它是原语),我能想到的最好的解决方案是创建像一个新的静态对象static String lock = "";,并附上x++x--一个内synchronized块,锁定上lock.但这似乎很尴尬.有没有更好的办法?

Dan*_*nov 6

使用AtomicInteger你想做的事情,并明确表示让操作x成为原子的意图.经过以下几次运行,我0每次都得到:

import java.util.concurrent.atomic.AtomicInteger;

public class DataRace implements Runnable {
    static volatile AtomicInteger x = new AtomicInteger(0);

    public void run() {
        for (int i = 0; i < 10000; i++) {
            x.incrementAndGet();
            x.decrementAndGet();
        }
    }

    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[100];

        for (int i = 0; i < threads.length; i++)
            threads[i] = new Thread(new DataRace());
        for (int i = 0; i < threads.length; i++)
            threads[i].start();
        for (int i = 0; i < threads.length; i++)
            threads[i].join();

        System.out.println(x); // x **is now** always 0!
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你甚至不需要`synchronized`,因为直到最后你才会看到`x`.如果没有`synchronized`,你会说允许JVM散布它喜欢的方法调用 - 一行中可以有两个增量,然后是两个减量.但这很好,因为只要增量的总数与减量的总数相同,并且只要每个增量/减量是原子的("AtomicInteger"保证),最终的总和仍然是0.你想在每个循环结束时检查0,然后你会在某些静态锁上"同步". (2认同)