我有2个代码片段,它们会做同样的事情,使线程安全。第一个使用Collections.synchronizedList,例如:
DataServiceRequest request = Collections.synchronizedList(new ArrayList<DataServiceRequest>());
第二个通过同步方法做同样的事情,例如:
public synchronized void addRequest(DataServiceRequest request) {
this.getRequests().add(request);
}
与上述两个例子的表现相比,最有效和最安全的方法是什么?
答案 0 :(得分:1)
第一个实际上只是第二个的语法糖(它返回一个包装列表,在每个调用周围放置synchronized (mutex)
),因此从性能的角度来看,它不太可能有任何区别。
至于#34;这是最安全的方式&#34; - 这取决于您的编码标准。如果您使用Collections.synchronizedList
,您必须注意这些文件,特别是:
至关重要的是,所有对支持列表的访问都是通过返回的列表完成的。
和
当迭代时,用户必须手动同步返回列表上的
在迭代控制同步的列表时,您仍会遇到同样的问题 - 这只是说synchronizedList
使用的互斥锁就是列表本身。如果您控制同步,则只需一致地使用相同的互斥锁即可对所有后备列表进行线程安全访问。
答案 1 :(得分:1)
您的问题可能意味着您不打算在所有列表操作上进行同步,而不仅仅是那些更改列表的操作。如果是这样,那么这将是错误的思考。但即使不是这样,使用synchronizedList
包装器也可以避免程序,因为它可以保证所有方法调用都是同步的。
synchronizedList
无法保证的一件事是在使用列表迭代器的代码块上进行同步。这仍然是您在自己的同步块中需要做的事情。