2011-11-21 45 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这样的东西来构造一个并发的弱散列映射。