我对SynchronizedList
有一个非常基本的问题。
假设我将synchronizedList作为 -
List syncList = Collections.synchronizedList(new ArrayList<>())
现在我的场景是线程A正在尝试访问add()
api和线程B试图访问synchronizedList的remove()
api。两个线程是否能够同时访问Both(添加和删除)api。
我相信线程不应该同时访问api(add()和remove())。如果我错了,请纠正我。
答案 0 :(得分:6)
Both线程是否能够访问Both(添加和删除)api 同时。
答案是否定的。
如果您有机会查看Collections.synchronizedList(List)
源代码,您会看到,该方法正在创建名为静态内部类的实例
SynchronizedList
或SynchronizedRandomAccessList
,具体取决于您作为参数发送的List
的类型。
现在这两个静态内部类都扩展了一个名为SynchronizedCollection
的公共类,该类维护一个mutex
对象,所有方法操作都在该对象上进行同步
此mutex
对象已分配this
,这实际上意味着mutex
对象是相同的返回实例。
由于add()
和remove()
方法是在
synchronized(mutex) {
}
阻止,执行add
的线程(并在mutex
上获取锁定),将不允许另一个线程执行{{1 (通过在同一个remove
上获取锁定),因为前者已经锁定 mutex
。 后一个帖子将等待,直到mutex
上前线程获得的锁定获得释放强>
所以,是mutex
和add()
互斥
答案 1 :(得分:1)
你能否“同时”澄清你的意思?
同步数据结构将强制两个线程中的一个等待,直到另一个线程完成其操作。 “等待锁定”可以在不同的粒度级别强制执行,并且可以在同步写入(包括删除)时允许读取,但原则保持不变。
答案 2 :(得分:0)
我会用这种方式解决你的问题:
首先我创建一个这样的列表包装类:
public class MySyncList{
private List<String> myList;
public MySyncList(){
this.myList = new ArrayList<String>();
}
public synchronized void add(String elem){
this.myList.add(elem);
}
public synchronized void remove(String elem){
this.myList.remove(remove);
}
public synchronized List<String> getList(){
return this.myList;
}
}
比从线程访问:
final MySyncList list = new MySyncList(); // final so other threads can access it
ExecutorService service = Executors.newFixedThreadPool(10);
for(int i=0;i<20;i++){
service.execute(new Runnable(){
public void run(){
list.add("something");
list.remove("something");
}
});
}
service.shutDown();
while(!service.isTerminated());
List<String> finalList = list.getList();
答案 3 :(得分:-1)
这是正确的,同步列表是完全线程安全的。因此,就原子性而言,线程将无法同时访问列表。不同线程的访问将以串行方式进行。