Lal*_*and 12 java multithreading synchronization
我已经像这样创建了synchronized arrayList
import java.text.SimpleDateFormat;
import java.util.*;
class HelloThread
{
int i=1;
List arrayList;
public void go()
{
arrayList=Collections.synchronizedList(new ArrayList());
Thread thread1=new Thread(new Runnable() {
public void run() {
while(i<=10)
{
arrayList.add(i);
i++;
}
}
});
thread1.start();
Thread thred2=new Thread(new Runnable() {
public void run() {
while(true)
{
Iterator it=arrayList.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
});
thred2.start();
}
}
public class test
{
public static void main(String[] args)
{
HelloThread hello=new HelloThread();
hello.go();
}
}
Run Code Online (Sandbox Code Playgroud)
但是像这样得到例外
线程"Thread-1"中的异常java.util.ConcurrentModificationException
我的方法有什么不对吗?
axt*_*avt 27
Iterator的synchronizedList是没有(不能)同步,您需要在列表中手动同步,而迭代(见的javadoc):
synchronized(arrayList) {
Iterator it=arrayList.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用a CopyOnWriteArrayList代替Collections.synchronizedList().它实现了写时复制语义,因此不需要同步.
Ste*_*n C 12
其他答案已经确定了问题:
同步集合的迭代器不同步.实际上,它们只是包装类中的集合对象返回的迭代器.
许多集合类(包括ArrayList)使用故障快速机制来检测迭代期间的并发修改.在各个类的javadoc中清楚地记录了这种行为.这就是你所看到的.
并非所有集合类都这样做.例如,许多java.util.Concurrent...集合类允许在迭代期间进行并发修改,但放宽迭代序列的语义,以便修改的结果在迭代器返回的对象中可能显而易见,也可能不显示.
用于Collections.synchronizedList() 解释如何同步迭代器的javadoc .基本上你这样做:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Run Code Online (Sandbox Code Playgroud)
(旁白:通常认为做这样的事情会起作用是不安全的.理论上,同步列表可以使用私有锁对象,并且该synchronized语句不会锁定并发修改.但是javadocs说这是什么做这种情况......所以这是安全的.)
这样做的问题是锁定集合会产生潜在的并发瓶颈.替代方法是使用写时复制数据结构,该数据结构在内部复制集合的相关部分.这种方法意味着迭代器看到了集合的快照.可以与迭代同时对集合进行修改,但迭代器不会看到它们.写时复制的问题在于修改可能要贵得多.
最终,您需要通过并发修改与实际需求来平衡不同集合类型的特征和成本.你能不能看到迭代器没有看到所有并发修改?
dog*_*ane 11
考虑使用线程安全的CopyOnWriteArrayList.每次添加项目时,都会创建基础数组的新副本.但是,迭代器不会反映自迭代器创建以来对列表的添加,但保证不会抛出ConcurrentModificationException.
arrayList=new CopyOnWriteArrayList();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
43730 次 |
| 最近记录: |