像这样的代码......
public void beforeUpdated(Log log){
synchronized(this){
query(log);
merge(log);
persist(log);
}
}
此方法在多线程环境下运行。日志的CRUD必须是原子操作。但只需要同步相同id的日志(log.getUuid())。如果我锁定所有操作,它必须表现不佳。我只希望同一个id的日志在原子操作下锁定。我该怎么做?如果你有任何想法,请帮帮我。谢谢。
答案 0 :(得分: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);
}
}
答案 1 :(得分:1)
您可以维护一个HashMap
,将迄今为止遇到的日志ID映射到某些Object
,并在属于正在写入的日志的id的Object
上进行同步至。请注意,必须在HashMap
本身上同步对HashMap
的读取和写入。
答案 2 :(得分: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);
}
}
如果从静态弱映射获取锁定的瓶颈困扰您,您可以尝试使用Guava MapMaker之类的东西构建并发弱哈希映射。