我从学生那里得到了这段代码,由于涉及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--
块中{1}}锁定synchronized
。但这似乎很尴尬。还有更好的方法吗?
答案 0 :(得分: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!
}
}
答案 1 :(得分:1)
AtomicInteger正是您要找的。 p>
答案 2 :(得分:1)
变量x
是静态的并且驻留在一个类中,因此应该在该类上同步对它的访问:要么创建一个静态方法,要么在DataRace.class
上使用synchronized块。