我有一个关于通过原子引用访问单个元素的问题。如果我有一个IntegerArray和它的原子引用;通过AtomicReference变量读取和写入数组的各个元素会导致数据竞争吗?
在下面的代码中: num是一个整数数组,aRnumbers是该数组的原子引用。在线程1和线程2中,我访问aRnumbers.get()1并将其增加1。
我能够通过原子引用访问各个元素,而不需要数据竞争,每次都要以22作为主线程中aRnumbers.get()1的输出,在两个线程完成之后。
但是,由于原子引用是在数组上定义的,而不是在单个元素上定义的;在这种情况下,不应该有一个数据竞争导致21/22作为输出吗?
在这种情况下,拥有数据竞赛不是AtomicIntegerArray数据结构为每个元素提供一个单独的AtomicReference的动机吗?
请在下面的java代码中找到我正在尝试run.Could的任何人,请让我知道我哪里出错了。
import java.util.concurrent.atomic.AtomicReference;
public class AtomicReferenceExample {
private static int[] num= new int[2];
private static AtomicReference<int[]> aRnumbers;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new MyRun1());
Thread t2 = new Thread(new MyRun2());
num[0]=10;
num[1]=20;
aRnumbers = new AtomicReference<int[]>(num);
System.out.println("In Main before:"+aRnumbers.get()[0]+aRnumbers.get()[1]);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("In Main after:"+aRnumbers.get()[0]+aRnumbers.get()[1]);
}
static class MyRun1 implements Runnable {
public void run() {
System.out.println("In T1 before:"+aRnumbers.get()[1]);
aRnumbers.get()[1]=aRnumbers.get()[1]+1;
}
}
static class MyRun2 implements Runnable {
public void run() {
System.out.println("In T2 before:"+aRnumbers.get()[1]);
aRnumbers.get()[1]=aRnumbers.get()[1]+1;
}
}
}发布于 2016-10-30 20:09:54
在这种情况下,难道不应该有一个数据竞赛导致输出为21/22吗?
的确有。您的线程寿命太短,很可能它们不在同一时间运行。
在这种情况下,拥有数据竞赛不是AtomicIntegerArray数据结构为每个元素提供一个单独的AtomicReference的动机吗?
是的,是这样的。
有谁能告诉我我哪里出错了吗?
启动线程需要1-10毫秒。
即使没有代码是JITed,增加这样的值可能会占用<< 50微秒。如果对其进行优化,每增加大约50到200纳米秒。
由于启动线程所需时间比运行时间长约20-200倍,因此不会同时运行,因此没有比赛条件。
尝试将值递增几百万次,这样您就有了一个争用条件,因为两个线程同时运行。
发布于 2016-10-30 20:15:49
递增元素由三个步骤组成:
种族状况可能会发生。举个例子:线程1读取值(比方说20)。任务切换。线程2读取值(再读20次),增加值并将其写回(21)。任务切换。第一个线程增加该值并将其写回(21)。因此,在进行2次递增操作时,最终值仍然只增加1次。
在这种情况下,数据结构没有帮助。线程安全集合有助于在并发线程添加、访问和删除元素时保持结构的一致性。但是在这里,您需要在增量操作的三个步骤中锁定对元素的访问。
https://stackoverflow.com/questions/40333054
复制相似问题