我有一个2个值的数组,我想保持细胞独立。因此,例如当一个线程获取第一个位置的锁时,该线程不会阻塞整个结构。
public DataStructure(int r, int i) {
this.r = r;
this.i = i;
values = new ArrayList<Integer>;
values.add(i);
values.add(r);
[...]
}
public void methodA() {
lock.lock();
[...]
values.get(0);
lock.unlock();
}
public void methodB() {
lock.lock();
[...]
values.get(1);
lock.unlock();
}
使用此代码,当一个线程获得methodA
上的锁定时,不可能使用其他线程来锁定methodB
。
我怎么做?
答案 0 :(得分:2)
您需要为每个单元格设置一个锁定对象。如果您只有两个值,那么
Object lock1 = new Object();
Object lock2 = new Object();
在类的标题中然后让方法A使用lock1声明一个synchronized块,而methodB使用lock2声明一个synchronized块。然后每个&#34;单元&#34;是独立锁定的。
e.g。
public void methodA() {
synchronized(lock1) {
[...]
values.get(0);
}
}
public void methodB() {
synchronized(lock2) {
[...]
values.get(1);
}
}
如果您将拥有大量独立单元格,那么为什么不声明一个具有锁定的单元格类,并将其用作每个单元格值的包装器。然后,您可以使用更通用的方法来访问线程安全的单元格内容。
e.g。
class Cell {
private Object lock;
private Object value;
public void doSomething() {
synchronized(lock) {
// something happens here with the value
}
}
}
但是,目前还不清楚您在线程安全方面的收获是什么。
答案 1 :(得分:1)
如果你想为数组中的每个元素分别使用一个锁,你可以使用Lock
个对象数组来匹配你的另一个数组,并依次锁定每个单元格。
或者,您可以考虑使用其中一个并发收藏集,例如CopyOnWriteArrayList
或ConcurrentHashMap
,具体取决于您的需求。
这些集合是线程安全的,并为您处理锁定。
答案 2 :(得分:1)
根据我对该问题的理解,java.util.concurrent
中的并发列表实现可能对您有所帮助。
您应该在此包中寻找CopyOnWriteArrayList
课程。
参考之前的SO问题,这完美地解释了它。
https://stackoverflow.com/a/10397154/2867032
CopyOnWriteArrayList
类是一个有趣的案例。它避免了 只读操作(如get和。)的并发瓶颈 包含,但它通过在变异中做更多的工作来做到这一点 操作,以及修改可见性规则。而且, 变异操作锁定整个列表,因此是一个 并发瓶颈。这些属性意味着CopyOnWriteArrayList
无法被称为通用并发 列表。
希望这会对你有所帮助。