3

x++我从一个学生那里得到了这段代码,由于涉及and的竞争条件,它不能正常工作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!
  }
}

由于我们无法同步 on x(因为它是原始的),我能想到的最佳解决方案是创建一个新的静态对象,例如并将andstatic String lock = "";包含在一个块中,锁定 on 。但这似乎真的很尴尬。有没有更好的办法?x++x--synchronizedlock

4

3 回答 3

6

UsingAtomicInteger做你想做的事,它明确了对x原子操作的意图。经过多次运行以下操作后,我0每次都得到 's :

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!
    }
}
于 2012-12-13T01:24:01.283 回答
1

AtomicInteger是您正在寻找的。

于 2012-12-13T01:22:25.293 回答
1

该变量x是静态的并且驻留在一个类中,因此对它的访问应该在该类上同步:要么创建一个静态方法,要么在DataRace.class.

于 2012-12-14T11:02:24.120 回答