我从学生那儿得到了这段代码,由于涉及x++x--的竞争条件,它无法正常工作。他尝试将synchronized添加到run()方法中,以消除该错误,但是显然,这仅排除了线程在同一对象上输入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!
  }
}

由于我们无法在x上进行同步(因为它是原始的),因此我能想到的最佳解决方案是创建一个新的静态对象(如static String lock = "";),并将x++x--封装在synchronized块中,从而锁定lock。但这似乎很尴尬。有没有更好的办法?

最佳答案

使用 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!
    }
}

10-01 09:33