假设我有以下代码:
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);
}
答案 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