我有这个小代码示例,在修改列表时,我用synchronized锁定它,但是在读取列表时它会出现ConcurrentModificationException,因为没有“synchronized”,锁定无效。是否可以为使用该对象的所有线程锁定一个对象,甚至是非同步的?
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
public static void main(String[] args) {
final Random r = new Random(System.currentTimeMillis());
List<Integer> list = new ArrayList<>();
new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (list) {
list.add(r.nextInt());
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
for (Integer i : list) {
System.out.println(i);
}
}
}
}).start();
}
}
backgorund是我不想改变我的代码中读取对象的所有部分
答案 0 :(得分:2)
您可以考虑使用List的并发实现,而不是ArrayList。也许是CopyOnWriteArrayList。
final List<Integer> list = new CopyOnWriteArrayList<Integer>();
答案 1 :(得分:1)
是否可以锁定使用该对象的所有线程的对象。
总之,不是。当一个线程进入synchronized(foo) {...}
块时,这不会阻止其他线程访问或修改foo
。它唯一阻止的是,它可以防止其他线程同时在同一个对象上同步。
你可以做什么,你是否可以创建自己的类来封装锁和锁保护的数据。
class MyLockedList {
private final Object lock = new Object();
private final List<Integer> theList = new ArrayList<>();
void add(int i) {
synchronized(lock) {
theList.add(i);
}
}
void printAll() {
synchronized(lock) {
for (Integer i : theList) {
System.out.println(... i ...);
}
}
}
...
}
答案 2 :(得分:0)
如果您可以修改同时使用该对象的功能,只需在每个关键部分添加synchronized
:
while (true) {
synchronized(list){
for (Integer i : list) {
System.out.println(i);
}
}
}
如果不能,请创建一个负责锁定线程的指定锁:
Lock lock = new Lock();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
如果其中一个函数已经执行某些锁定,后者可能会减慢进程的速度,但这样可以确保始终同步对并发对象的访问。