[英]synchronized vs ReadWriteLock
嗨,我在以下代碼段中極大地簡化了Java問題
public class WhichJavaSynchroIsBestHere {
private BlockingQueue<CustomObject> queue = new PriorityBlockingQueue<CustomObject>();
public void add( CustomObject customO ) {
// The custom objects do never have the same id
// so it's no horizontal concurrency but more vertical one a la producer/consumer
if ( !queue.contains( customO ) ) {
// Between the two statement a remove can happen
queue.add( customO );
}
}
public void remove( CustomObject customO ) {
queue.remove( customO );
}
public static class CustomObject {
long id;
@Override
public boolean equals( Object obj ) {
if ( obj == null || getClass() != obj.getClass() )
return false;
CustomObject other = (CustomObject) obj;
return ( id == other.id;
}
}
}
因此,這更多的生產者/使用者問題,因為大概兩個調用add的線程不會傳遞相同的Customobject
(id),但是如果一個線程正在調用add且對象與另一個線程調用remove的對象相同,則可能會發生這種情況。 在if條件和添加之間的代碼段在我看來不是線程,安全,我在考慮對象Lock(無synchronized
塊)來保護該段,但是ReadWriteLock
更好嗎?
這沒有什么區別,因為無論如何這兩個部分都需要寫鎖定。
ReadWriteLock的優點是可以輕松地允許可以使用共享訪問權限的多個Reader,並且與需要獨占訪問權限才能進行寫作的人員很好地合作。
您可以在“ contains
代碼的周圍加上“讀取”鎖定,如果您將大量重復工作放在可能的工作中,那將是有道理的。 但是,如果比起工作的主要驅動因素(而不是測試的大部分時間都通過了),這更是一種針對極端情況的健全性檢查,那么在這種情況下就沒有理由進行讀取鎖定。 只需鎖定整個部分並完成即可。
在if條件和添加之間的代碼段對我來說似乎不是線程安全的
您是正確的,它不是線程安全的。 每當對一個對象進行多次調用(甚至是synchronized
調用)時,如果多個線程訪問該對象,則需要擔心兩次調用之間對象的狀態會發生變化。 不僅僅是對象可能已被刪除,而且另一個生產者可能添加了重復的對象,從而導致隊列中出現重復。 比賽將是:
隊列中將有2個A副本。
我在考慮對象鎖(無同步塊)以保護該部分
如果您由於察覺到的性能問題而避開了synchronized
,那么請不要這樣做。 這是適合使用synchronized
的最佳示例。 如果您在synchronized
塊內執行所有操作,則可以擺脫BlockingQueue
。
ReadWriteLock更好嗎?
否,因為在兩種情況下,線程都是“寫入”隊列。 刪除將修改隊列與添加隊列一樣多。 如果沒有作者,但對寫線程具有獨占訪問權,則ReadWriteLock
允許多個閱讀線程。 現在,對隊列的測試被視為已讀,但這不會為您節省很多,除非在很大的情況下,隊列中已經存在重復項。
另外,要非常注意queue.contains(customO)
。 大多數隊列(包括PriorityBlockingQueue
)在隊列中的所有項目中運行,以查找您可能要添加的項目( O(N)
)。 這可能非常昂貴,具體取決於集合中有多少個項目。
在我看來,這是使用ConcurrentSkipListSet
的好地方。 您只需執行一個queue.add()即可which internally does a put-if-absent. You can do a
which internally does a put-if-absent. You can do a
queue.pollFirst()`刪除並獲取第一項。 然后,該集合將為您處理內存同步和鎖定,並解決爭用條件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.