这是班级:
public class Saver {
private static ArrayList<String> nameCache = new ArrayList<>();
public static synchronized void add(ArrayList<String> names) {
nameCache.addAll(names);
}
public static synchronized void save() {
for (String name : nameCache) {
//write name
}
nameCache.clear();
}
}
不同的线程将调用save并以不同的顺序添加。 但是这个synchronized关键字会使这个进程线程安全吗?
这是解决并发问题的正确方法,如果不是解决此问题的好方法吗?
答案 0 :(得分:2)
同步在Saver
课程中完成,一次只有一个Thread
可以访问nameCache
。
答案 1 :(得分:2)
这是线程安全的,因为你不会让线程相互踩踏。在类级锁上进行同步可确保一次只有一个线程可以访问列表,并且任何一个线程的更改都将对所有其他线程可见,因此hahn's answer是正确的(+1来自我)。但关于这个问题
这是解决并发问题的正确方法,如果不是解决此问题的好方法
答案是,&#34;它取决于上下文,但总的来说没有。&#34;
每个线程都必须等待同一个锁,当列表被保存时,每个想要添加内容的线程都必须等待。这可能会产生不可接受的性能问题,具体取决于负载和列表保存的频率。
解决方案取决于具体情况,但通常会尽量减少保存方法保持锁定所需的时间。你可能有保存方法制作列表的副本,只保持锁定的时间足以制作副本,然后保存列表的副本,以便其他线程可以在副本保存的同时调用add方法
缓存是一种比你想象的更危险的事情(我是否保存了过时的项目?什么时候缓存需要过期?我是在创建内存泄漏吗?等等),它也是一个技术实现细节往往与业务逻辑混合在一起,这使得代码更加难以理解。使数据和方法静态将全局状态引入可能使测试变得困难的应用程序,使数据和方法属于对象实例,并使用依赖注入将其注入所需的位置可能是优选的。