Java 原子引用的单个元素上的数据竞争
我有一个关于通过原子引用访问单个元素的问题。 如果我有一个整数数组和对它的原子引用;通过AtomicReference变量读取和写入数组的各个元素是否会导致数据争用 在下面的代码中:num是一个整数数组,aRnumbers是数组的原子引用。 在螺纹1和2中;我访问aRnumbers.get()[1]并将其递增1 我能够通过原子引用访问单个元素,而无需每次都进行数据竞争,以获得准确的结果,在两个线程完成后,主线程中的aRnumbers.get()[1]输出为22 但是,由于原子引用是在数组上定义的,而不是在单个元素上定义的;在这种情况下,不应该有数据竞争导致21/22作为输出吗 在这种情况下,数据竞争不是拥有一个AtomicIntegerArray数据结构的动机吗?它为每个元素提供一个单独的原子引用 请在下面找到我正在尝试运行的java代码。请任何人告诉我哪里出了问题Java 原子引用的单个元素上的数据竞争,java,arrays,multithreading,atomicreference,Java,Arrays,Multithreading,Atomicreference,我有一个关于通过原子引用访问单个元素的问题。 如果我有一个整数数组和对它的原子引用;通过AtomicReference变量读取和写入数组的各个元素是否会导致数据争用 在下面的代码中:num是一个整数数组,aRnumbers是数组的原子引用。 在螺纹1和2中;我访问aRnumbers.get()[1]并将其递增1 我能够通过原子引用访问单个元素,而无需每次都进行数据竞争,以获得准确的结果,在两个线程完成后,主线程中的aRnumbers.get()[1]输出为22 但是,由于原子引用是在数组上定义的
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;
}
}
}
导入java.util.concurrent.AtomicReference;
公共类原子引用示例{
私有静态int[]num=新int[2];
私有静态原子参考数;
公共静态void main(字符串[]args)引发InterruptedException{
线程t1=新线程(新的MyRun1());
线程t2=新线程(新的MyRun2());
num[0]=10;
num[1]=20;
aRnumbers=新的原子引用(num);
System.out.println(“在Main之前:+aRnumbers.get()[0]+aRnumbers.get()[1]);
t1.start();
t2.start();
t1.join();
t2.连接();
System.out.println(“在Main之后:+aRnumbers.get()[0]+aRnumbers.get()[1]);
}
静态类MyRun1实现Runnable{
公开募捐{
System.out.println(“在T1之前:+aRnumbers.get()[1]);
aRnumbers.get()[1]=aRnumbers.get()[1]+1;
}
}
静态类MyRun2实现Runnable{
公开募捐{
System.out.println(“在T2之前:+aRnumbers.get()[1]);
aRnumbers.get()[1]=aRnumbers.get()[1]+1;
}
}
}
在这种情况下,不应该有数据竞争导致21/22作为输出吗
确实有。您的线程寿命很短,很可能没有同时运行
在这种情况下,数据竞争不是拥有一个AtomicIntegerArray数据结构的动机吗?它为每个元素提供一个单独的原子引用
是的
谁能告诉我哪里出了问题
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;
}
}
}
启动线程需要1-10毫秒
即使代码没有被JIT处理,增加这样的值也可能需要花费大量时间
在这种情况下,不应该有数据竞争导致21/22作为输出吗
确实有。您的线程寿命很短,很可能没有同时运行
在这种情况下,数据竞争不是拥有一个AtomicIntegerArray数据结构的动机吗?它为每个元素提供一个单独的原子引用
是的
谁能告诉我哪里出了问题
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;
}
}
}
启动线程需要1-10毫秒
即使没有JIT代码,也要增加这样的值,这可能需要增加元素包括三个步骤:
在这种情况下,数据结构没有帮助。线程安全集合有助于在并发线程添加、访问和删除元素时保持结构一致。但在这里,您需要在增量操作的三个步骤中锁定对元素的访问。增加元素包括三个步骤:
在这种情况下,数据结构没有帮助。线程安全集合有助于在并发线程添加、访问和删除元素时保持结构一致。但在这里,您需要在增量操作的三个步骤中锁定对元素的访问。是的,根据我的理解,这也是应该发生的。不幸的是(或者更幸运的是)没有,我得到了22作为最终值。我将num[1]初始化为0,并将两个线程中的引用分别递增1000次,现在的预期输出为2000,是的,我确实获得了数据竞赛,但2000从来不是最终输出。对于(int i=0;iAs其他人建议尝试1000000次。对于现代CPU来说这算不了什么。是的,根据我的理解,这也是应该发生的。不幸的是(或者更幸运的是),它没有发生,我得到22作为最终值。我初始化了num[1]在2个线程中,每个线程的引用增加了1000倍,现在预期的输出是2000,是的,我确实得到了数据竞赛,2000从来不是最终输出。对于(int I=0;iAs其他人建议尝试1000000次。这对现代CPU来说不算什么。是的,完美!!我初始化了num[1]为0,并在2 t中分别将参考值增加1000倍