2011-11-21 48 views
4

這樣的代碼......如何在這種情況下添加鎖?

public void beforeUpdated(Log log){ 
    synchronized(this){ 
     query(log); 
     merge(log); 
     persist(log); 
    } 
} 

該方法是在多線程environment.The日誌CRUD運行的必須是同一個ID(log.getUuid())需要的原子operation.But僅日誌如果我鎖定所有的操作,它一定是一個糟糕的表現。我只是希望同一個id的日誌在原子操作下鎖定。我應該怎麼做?請幫助我,如果你有任何想法,謝謝。

+2

我會添加一切到單線程後臺線程池。如果速度足夠快,則不需要任何額外的鎖定。 –

回答

1

您可以維護一個HashMap,它將迄今爲止遇到的日誌ID映射到某些Object,並在屬於正在寫入的日誌的ID的Object上進行同步。請注意,讀取和寫入HashMap必須在HashMap本身上同步。

+0

您需要一個HashMap,以便您可以執行get()來查找匹配的對象。一組將不會給你匹配的對象。 –

+0

@PeterLawrey:對;我已經更新了我的答案。 –

5

我遇到過這種情況幾次。你需要的是一個單例LockFactory,它實際上是一個鎖對象的弱引用字典。代碼應該是這樣的:

class LockFactory { 
    private LockFactory() {} 
    private LockFactory instance = null; 
    public static LockFactory getInstance() { 
     if (this.instance == null) 
      this.instance = new LockFactory(); 
     return this.instance; 
    } 
    private int _last_check_size = 0; 
    private int _cleanup_size = 1000; 
    private Map<String, WeakReference> weakRefDictionary = new HashMap<String, WeakReference>(); 
    public object getLock(String id) { 
     synchronized(this) { 
      if (!this.weakRefDictionary.containsKey(id)) 
       this.weakRefDictionary.put(id, new WeakReference(null)); 
      Object lock = this.weakRefDictionary.get(id).Target; 
      if (lock == null) { 
       lock = new Object(); 
       this.weakRefDictionary.get(id).Target = lock; 
      } 
      if (this.weakRefDictionary.size() > this._last_check_size + this._cleanup_size) 
        this._do_cleanup(); 
      return lock; 
     } 
    } 
    public void _do_cleanup() { 
     synchronized(this) { 
      Iterator<Map.Entry<String, WeakReference>> iter = this.weakRefDictionary.entrySet().iterator(); 
      while (iter.hasNext()) { 
       Map.Entry<String,WeakReference> entry = iter.next(); 
       if (entry.getValue().get() == null) { 
        iter.remove(); 
       } 
      } 
      this._last_check_size = this.weakRefDictionary.size(); 
     } 
    } 
} 

現在你的情況使用只是做:

public void beforeUpdated(Log log){ 
    synchronized(LockFactory.getInstance().getLock(log.getUuid())){ 
     query(log); 
     merge(log); 
     persist(log); 
    } 
} 
+0

鎖不會被立即丟棄,因爲當它沒有被鎖定時,沒有其他強烈的引用。 –

+1

由於對象被保存在堆棧中直到它被釋放,所以有一個引用 – idanzalz

+0

好點,這是唯一重要的時間。 –

0

一個建議是做一些事情,如:

class Log 
{ 
    private static final WeakHashMap<String, Object> LOCKS = 
     new WeakHashMap<String, Object>(); 

    private final String uuid; 

    public Log(String uuid) 
    { 
     this.uuid = uuid; 
    } 

    public Object getLock() 
    { 
     synchronized (LOCKS) 
     { 
      Object lock = LOCKS.get(uuid); 
      if (lock == null) 
      { 
       lock = new Object(); 
       LOCKS.put(uuid, lock); 
      } 
      return lock; 
     } 
    } 
} 

,並用它作爲:

public void beforeUpdated(Log log) 
{ 
    synchronized (log.getLock()) 
    { 
     query(log); 
     merge(log); 
     persist(log); 
    } 
} 

如果acqui的瓶頸從靜態弱映射環鎖定困擾你,你可以嘗試使用像Guava MapMaker這樣的東西來構造一個併發的弱散列映射。