这个类线程对不同的线程安全吗?

时间:2016-02-19 15:52:15

标签: java multithreading concurrency thread-safety

这是班级:

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关键字会使这个进程线程安全吗?

这是解决并发问题的正确方法,如果不是解决此问题的好方法吗?

2 个答案:

答案 0 :(得分:2)

同步在Saver课程中完成,一次只有一个Thread可以访问nameCache

答案 1 :(得分:2)

这是线程安全的,因为你不会让线程相互踩踏。在类级锁上进行同步可确保一次只有一个线程可以访问列表,并且任何一个线程的更改都将对所有其他线程可见,因此hahn's answer是正确的(+1来自我)。但关于这个问题

  

这是解决并发问题的正确方法,如果不是解决此问题的好方法

答案是,&#34;它取决于上下文,但总的来说没有。&#34;

每个线程都必须等待同一个锁,当列表被保存时,每个想要添加内容的线程都必须等待。这可能会产生不可接受的性能问题,具体取决于负载和列表保存的频率。

解决方案取决于具体情况,但通常会尽量减少保存方法保持锁定所需的时间。你可能有保存方法制作列表的副本,只保持锁定的时间足以制作副本,然后保存列表的副本,以便其他线程可以在副本保存的同时调用add方法

缓存是一种比你想象的更危险的事情(我是否保存了过时的项目?什么时候缓存需要过期?我是在创建内存泄漏吗?等等),它也是一个技术实现细节往往与业务逻辑混合在一起,这使得代码更加难以理解。使数据和方法静态将全局状态引入可能使测试变得困难的应用程序,使数据和方法属于对象实例,并使用依赖注入将其注入所需的位置可能是优选的。