Collections.synchronizedList() 方法有什么用?似乎没有同步列表 [英] What is the use of Collections.synchronizedList() method? It doesn't seem to synchronize the list
问题描述
我正在尝试使用两个线程将 String
值添加到 ArrayList
.我想要的是,当一个线程添加值时,另一个线程不应该干扰,所以我使用了 Collections.synchronizedList
方法.但似乎如果我没有在对象上显式同步,则添加是以不同步的方式完成的.
I am trying to add String
values to an ArrayList
using two threads. What I want is that while one thread is adding the values the other thread should not interfere so I have used the Collections.synchronizedList
method. But it appears that if I don't explicitly synchronize on an object the adding is done in an unsynchronized way.
没有显式同步块:
public class SynTest {
public static void main(String []args){
final List<String> list=new ArrayList<String>();
final List<String> synList=Collections.synchronizedList(list);
final Object o=new Object();
Thread tOne=new Thread(new Runnable(){
@Override
public void run() {
//synchronized(o){
for(int i=0;i<100;i++){
System.out.println(synList.add("add one"+i)+ " one");
}
//}
}
});
Thread tTwo=new Thread(new Runnable(){
@Override
public void run() {
//synchronized(o){
for(int i=0;i<100;i++){
System.out.println(synList.add("add two"+i)+" two");
}
//}
}
});
tOne.start();
tTwo.start();
}
}
我得到的输出是:
true one
true two
true one
true two
true one
true two
true two
true one
true one
true one...
在取消注释显式同步块的情况下,我在添加时停止了来自其他线程的干扰.一旦线程获得了锁,它就会一直执行直到完成.
With the explicit synchronized block uncommented I'm stopping the interference from the other thread while adding. Once the thread has acquired the lock it is executing until it is finished.
取消注释同步块后的示例输出:
sample output after uncommenting the synchronized block:
true one
true one
true one
true one
true one
true one
true one
true one...
那么为什么 Collections.synchronizedList()
不进行同步?
So why is the Collections.synchronizedList()
not doing the synchronization?
推荐答案
同步列表只同步这个列表的方法.
A synchronized list only synchronizes methods of this list.
这意味着一个线程将无法修改列表,而另一个线程当前正在运行此列表中的方法.处理方法时对象被锁定.
It means a thread won't be able to modify the list while another thread is currently running a method from this list. The object is locked while processing method.
举个例子,假设有两个线程在你的列表上运行 addAll
,有 2 个不同的列表(A=A1,A2,A3
和 B=B1,B2,B3
) 作为参数.
As an example, Let's say two threads run addAll
on your list, with 2 different lists (A=A1,A2,A3
and B=B1,B2,B3
) as parameter.
由于方法是同步的,您可以确保这些列表不会像
A1,B1,A2,A3,B2,B3
您不能决定一个线程何时将进程移交给另一个线程.每个方法调用都必须完全运行并返回,然后另一个方法才能运行.所以你可以得到 A1,A2,A3,B1,B2,B3
或 B1,B2,B3,A1,A2,A3
(因为我们不知道哪个线程调用将首先运行).
You don't decide when a thread handover the process to the other thread. Each method call has to fully run and return before the other one could run. So you can either get A1,A2,A3,B1,B2,B3
or B1,B2,B3,A1,A2,A3
(As we don't know which thread call will run first).
在您的第一段代码中,两个线程同时运行.两者都尝试将一个元素 add
添加到列表中.除了 add
方法上的同步之外,您没有任何方法可以阻止一个线程,因此没有什么可以阻止线程 1 在将进程移交给线程 2 之前运行多个 add
操作. 所以你的输出完全正常.
In your first piece of code, both threads runs on the same time. And both try to add
an element to the list. You don't have any way to block one thread except the synchronization on the add
method so nothing prevent thread 1 from running multiple add
operation before handing over the process to thread 2. So your output is perfectly normal.
在您的第二段代码(未注释的)中,您明确指出一个线程在开始循环之前完全锁定了另一个线程的列表.因此,您要确保您的一个线程在另一个线程访问列表之前运行完整循环.
In your second piece of code (the uncommented one), you clearly state that a thread completely lock the list from the other thread before starting the loop. Hence, you make sure one of your thread will run the full loop before the other one could access the list.
这篇关于Collections.synchronizedList() 方法有什么用?似乎没有同步列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!