- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想知道 Java 中是否有一种方法可以使用两个锁对象进行同步。我的意思不是锁定任一个对象,我的意思是只锁定两者。
例如如果我有 4 个线程:
在上面的场景中,线程 A 和线程 D 将共享一个锁,但线程 B 和线程 C 将拥有自己的锁。即使它们与两个对象之一重叠,相同的锁也仅在两个对象重叠时才适用。
所以我有一个由许多线程调用的方法,它将根据特定的数据库执行特定的 Activity 类型。我有数据库和 Activity 的标识符对象,我可以保证该操作是线程安全的,只要它不是基于与另一个线程相同的数据库的相同 Activity 。
我理想的代码应该是这样的:
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.
}
}
我可以创建由 DatabaseIdentifier 和 ActivityIdentifier 键控的锁对象的散列映射,但是当我需要以线程安全的方式创建/访问这些锁时,我将遇到相同的同步问题。
现在我只是在 DatabaseIdentifier 上进行同步。一个 DBIdentifier 同时进行多项 Activity 的可能性要小得多,因此我很少会过度锁定。 (虽然不能说相反的方向相同。)
有没有人有解决这个问题的好方法而不涉及强制不必要的线程等待?
谢谢!
最佳答案
让每个 DatabaseIdentifier
保留一组锁定到它拥有的 ActivityIdentifier
的锁
所以你可以调用
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.
}
}
那么你只需要在 dbID
中对底层集合(使用 ConcurrentHashMap)进行(短)锁
换句话说
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;
}
这比锁定 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);
}
关于java - 有没有办法在 Java 中使用两个锁对象进行同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7985971/
我是一名优秀的程序员,十分优秀!