繁体   English   中英

定义线程安全类的两种方法之间的区别

[英]Difference between two ways of defining a thread safe class

我想知道下面两个示例类在功能上有什么不同。 应该优先选择哪种样式以及为什么。

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();
    }
}

要么

public class MyQueue {
    private Queue<Abc> q;

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

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

    public synchronized Abc get() {
        return q.remove();
    }
}

我的看法是-就个人的喜好而言,就班级中的这一功能而言,两者都可以很好地工作。

请让我知道是否还有更多区别。

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

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

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

根据您的类用例,它可能带来好处或引起问题。

第一个实现隐藏了同步细节的事实为您将来添加新功能提供了更大的灵活性(例如,您可以根据需要在put()get()方法中添加一些未同步的代码),但要付出轻微的代价,就是在您的列表周围增加一层。

否则,所提供的功能没有任何区别。

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

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

但是在某些情况下,最好使用包装程序提供的同步机制,例如ConcurrentHashMap的情况。

例如,如果您要保护自己对简单的非线程安全的HashMap的访问,则可以锁定任何读/写操作的整个映射(所有键),这会影响映射的并发性。 相反,ConcurrentHashMap仅锁定映射的键集,因此使用它进行读/写并发操作时可以获得更好的性能。

谢谢!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM