[英]Java concurrent access of ArrayList
After the following code 以下代码之后
ArrayList<String> foo, bar, test;
foo = new ArrayList<String>(Arrays.asList("foo"));
bar = new ArrayList<String>(Arrays.asList("bar"));
test = new ArrayList<String>(Arrays.asList("test"));
Thread 1 runs: 线程1运行:
foo = new ArrayList<String>(bar);
Thread 2 runs: 线程2运行:
bar = new ArrayList<String>(test);
Can this cause an exception if Thread 2 changes value of bar
while it is being used by Thread 1? 如果线程2在线程1使用它时更改bar
值,这会引起异常吗?
You won't get a concurrent modification exception, since the list instances are never mutated. 您不会遇到并发修改异常,因为列表实例永远不会发生突变。 Only references are exchanged. 仅参考被交换。
However you still have a data race: 但是,您仍然有数据竞赛:
bar
object and create a new `foo´ which is the copy of that. Thread1将捕获初始的bar
对象并创建一个新的“ foo”,该副本是该对象的副本。 bar
reference, and when Thread1 runs later on it will end up with a copy of that one, which itself is a copy of the test
list. 否则,将首先运行Thread2中的分配,这意味着它将创建一个存储在bar
引用中的新列表,并且当稍后运行Thread1时,它将得到该列表的副本,该副本本身就是test
列表的副本。 。 It is not a problem at all. 这根本不是问题。 To understand what happens you need to know how java handles such structures as ArrayList
(and other collections). 要了解发生了什么,您需要知道java如何处理ArrayList
(和其他集合)之类的结构。
When you create a new ArrayList
variable, the variable contains only the link to the segment of RAM where the real data is kept. 创建new ArrayList
变量时,该变量仅包含指向保留实际数据的RAM段的链接。 When you pass the variable to a constructor or another method, java
copies the value of the variable, and the parameter is initialized with this value. 当您将变量传递给构造函数或其他方法时, java
复制变量的值,并使用该值初始化参数。 So when you assign a new list to the parameter, you don't change the value of the original variable: 因此,当您为参数分配新列表时,无需更改原始变量的值:
public class Main {
public static void main(String [] args) throws IOException {
List<String> foo, bar, test;
foo = new ArrayList<String>(Arrays.asList("foo"));
bar = new ArrayList<String>(Arrays.asList("bar"));
test = new ArrayList<String>(Arrays.asList("test"));
CountDownLatch cdl = new CountDownLatch(1);
Thread r1 = new Thread(new MyThread("foo = new ArrayList(bar)", bar, foo, cdl));
Thread r2 = new Thread(new MyThread("bar = new ArrayList(test)", test, bar, cdl));
r1.start();
r2.start();
cdl.countDown();
System.out.println("Size of foo is " + foo.size());
System.out.println("Size of bar is " + foo.size());
}
}
class MyThread implements Runnable {
private List<String> src;
private List<String> dst;
private CountDownLatch cdl;
private String msg;
public MyThread(String msg, List<String> src, List<String> dst, CountDownLatch cdl) {
this.msg = msg;
this.src = src;
this.dst = dst;
this.cdl = cdl;
}
@Override
public void run() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
dst = new ArrayList<String>(src);
dst.add("test");
System.out.println(msg + " and my size is " + dst.size());
}
}
Output: 输出:
bar = new ArrayList(test) and my size is 2
foo = new ArrayList(bar) and my size is 2
Size of foo is 1
Size of bar is 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.