Jef*_*erg 3 java multithreading synchronized
我想知道Java中是否有一种方法可以使用两个锁对象进行同步。我的意思不是锁定任何一个对象,而是仅锁定两个对象。
例如,如果我有 4 个线程:
在上面的场景中,线程 A 和线程 D 将共享一个锁,但线程 B 和线程 C 将拥有自己的锁。即使它们与两个对象之一重叠,但只有在两个对象都重叠时才应用相同的锁。
所以我有一个由许多线程调用的方法,它将根据特定的数据库执行特定的活动类型。我有数据库和活动的标识符对象,并且我可以保证该操作将是线程安全的,只要它不是基于与另一个线程相同的数据库的相同活动。
我理想的代码看起来像这样:
public void doActivity(DatabaseIdentifier dbID, ActivityIdentifier actID) {
synchronized( dbID, actID ) { // <--- Not real Java
// Do an action that can be guaranteed thread-safe per unique
// combination of dbIT and actID, but needs to share a
// lock if they are both the same.
}
}
Run Code Online (Sandbox Code Playgroud)
我可以创建一个由 DatabaseIdentifier 和 ActivityIdentifier 键入键控的锁对象的哈希图,但是当我需要以线程安全的方式创建/访问这些锁时,我将遇到相同的同步问题。
现在我只是在 DatabaseIdentifier 上进行同步。对于一个 DBIdentifier 同时进行多个活动的可能性要小得多,因此我很少会过度锁定。(但不能对相反的方向说同样的话。)
任何人都有一个好的方法来处理这个问题,而不涉及强制不必要的线程等待?
谢谢!
每个人都DatabaseIdentifier保留一套锁,钥匙上有ActivityIdentifier它所拥有的 s
所以你可以打电话
public void doActivity(DatabaseIdentifier dbID, ActivityIdentifier actID) {
synchronized( dbID.getLock(actID) ) {
// Do an action that can be guaranteed thread-safe per unique
// combination of dbIT and actID, but needs to share a
// lock if they are both the same.
}
}
Run Code Online (Sandbox Code Playgroud)
那么你只需要在底层集合上有一个(短)锁(使用 ConcurrentHashMap)dbID
换句话说
ConcurrentHashMap<ActivityIdentifier ,Object> locks = new...
public Object getLock(ActivityIdentifier actID){
Object res = locks.get(actID); //avoid unnecessary allocations of Object
if(res==null) {
Object newLock = new Object();
res = locks.puIfAbsent(actID,newLock );
return res!=null?res:newLock;
} else return res;
}
Run Code Online (Sandbox Code Playgroud)
这比锁定 dbID 上的完整操作要好(尤其是当操作很长时),但仍然比您的理想情况更糟糕
更新以响应有关 EnumMap 的评论
private final EnumMap<ActivityIdentifier ,Object> locks;
/**
initializer ensuring all values are initialized
*/
{
EnumMap<ActivityIdentifier ,Object> tmp = new EnumMap<ActivityIdentifier ,Object>(ActivityIdentifier.class)
for(ActivityIdentifier e;ActivityIdentifier.values()){
tmp.put(e,new Object());
}
locks = Collections.unmodifiableMap(tmp);//read-only view ensures no modifications will happen after it is initialized making this thread-safe
}
public Object getLock(ActivityIdentifier actID){
return locks.get(actID);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2390 次 |
| 最近记录: |