Java 定义线程安全类的两种方法之间的差异

Java 定义线程安全类的两种方法之间的差异,java,multithreading,collections,synchronization,Java,Multithreading,Collections,Synchronization,我想知道在下面的两个示例类中有什么功能上的区别。哪种风格应该比另一种更受欢迎,以及为什么 public class MyQueue { private Queue<Abc> q; public MyQueue() { q = Collections.synchronizedList(new LinkedList<Abc>()); } public void put(Abc obj) { q.add(obj

我想知道在下面的两个示例类中有什么功能上的区别。哪种风格应该比另一种更受欢迎,以及为什么

public class MyQueue {
    private Queue<Abc> q;

    public MyQueue() {
        q = Collections.synchronizedList(new LinkedList<Abc>());
    }

    public void put(Abc obj) {
        q.add(obj);
    }

    public Abc get() {
        return q.remove();
    }
}
公共类MyQueue{
专用队列q;
公共MyQueue(){
q=Collections.synchronizedList(新的LinkedList());
}
公开作废认沽权证(Abc obj){
q、 添加(obj);
}
公共Abc get(){
返回q.remove();
}
}

公共类MyQueue{
专用队列q;
公共MyQueue(){
q=新的LinkedList();
}
公共同步作废认沽权(Abc obj){
q、 添加(obj);
}
公共同步Abc get(){
返回q.remove();
}
}
我的看法是——这两种方法都可以很好地发挥课堂上的功能,这只是个人喜好的问题


请让我知道它是否有更多的不同。

主要的架构差异是第二个实现将同步监视器(对象本身)公开给外部世界。这意味着每个人都可能获得用于内部同步的相同锁:

MyQueue myQueue = new MyQueue();  // a shared instance

synchronized(myQueue) {
    // No one else can call synchronized methods while you're here
}
根据您的类用例,它可能带来好处或导致问题

第一个实现隐藏了同步的细节,这一事实为您将来添加新功能提供了更大的灵活性(例如,如果需要,您可以在
put()
get()
方法中添加一些未同步的代码),但是在你的列表中增加一层会带来一个小的惩罚

否则,给出的功能没有区别


注意:不要忘记在
q
声明中添加
final
。否则,您的类不能保证所谓的安全发布,也不能称为完全线程安全。

对于列表,通过包装器访问它或使用同步块保护对它的每次访问之间的功能应该没有任何区别

但在某些情况下,最好使用包装器提供的同步机制,ConcurrentHashMap就是这样

例如,如果您注意保护自己对一个简单的非线程安全HashMap的访问,您将为任何读/写锁定整个map(所有键),这将影响map上的并发性。相反,ConcurrentHashMap只锁定映射的密钥集,所以在读/写并发操作中使用它可以获得更好的性能


谢谢

在这种简化的情况下,没有什么区别,只是
synchronizedList()
LinkedList
周围添加了一个包装器,因此所有调用都必须委派。第二个版本没有额外的方法委派层。我喜欢公开锁的点,所以基本上我的添加、删除可以与任何外部同步块同步,如果有人想这样对齐它的话。
MyQueue myQueue = new MyQueue();  // a shared instance

synchronized(myQueue) {
    // No one else can call synchronized methods while you're here
}