使用与线程安全集合同步



假设我有以下代码:

    private ConcurrentHashMap<Integer, Book> shelf;
    public Library(ConcurrentHashMap<Integer, Book> shelf){         
        this.shelf = new ConcurrentHashMap<Integer, Book>(shelf);       
    }

鉴于我使用的是线程安全集合,可以使用以下方法还是需要担心线程安全?

    public void addBook(int index, Book add){
        shelf.put(index, add);
    }

如果上述方法使用不安全,添加同步是否是正确的方法?这样

public synchronized void addBook(int index, Book add){
    shelf.put(index, add);
}

如果您只调用shelf.put,则无需担心。由于put已经是线程安全的,因此您可以。

当您执行多个需要原子操作时,您需要担心同步。例如,也许您有一个名为 updateBook 的方法,如下所示

public void updateBook(int index, String newTitle){
    Book book = shelf.get(index);
    // do something with book or maybe update book.setTitle(newTitle);
    shelf.put(index, book);
}
必须

synchronized此方法,因为否则其他线程可能会获得尚未更新的书籍。

synchronized 关键字实质上是在整个addBook方法周围放置了一个互斥锁。

ConcurrentHashMap可确保所有操作(例如 put)都是线程安全的,但结合使用检索操作(例如 get)可能会导致您遇到以下情况:您在放置的同时从 Hashmap 中检索内容,并获得意外结果。

单独地,ConcurrentHashMap中的所有方法都是线程安全的,但在单独的线程中结合使用时,您不一定确定它们的执行顺序。(感谢@jtahlborn的澄清)。

因此,在您的特定情况下,将 synchronized 关键字添加到 addBook 方法是多余的。

如果您正在执行涉及多个检索和放置的更复杂的操作,则可能需要考虑一些无关的锁定(您自己的互斥锁)。

请参阅:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html

最新更新