使用与线程安全集合同步?

时间:2016-02-05 17:25:55

标签: java multithreading

假设我有以下代码:

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

如果上述方法无法安全使用,那么添加synchronized会是正确的方法吗?像这样,

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

2 个答案:

答案 0 :(得分:1)

如果您只是致电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,否则另一个线程可以得到一本尚未更新的书。

答案 1 :(得分:0)

synchronized关键字实际上会在整个addBook方法中设置互斥锁。

ConcurrentHashMap确保所有操作(例如put)都是线程安全的,但是结合使用检索操作(例如get)可能会导致您遇到从Hashmap检索内容的情况。同时你正在推杆,并获得意想不到的结果。

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

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

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

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