如何同步整数数组的单个元素?

时间:2011-10-13 09:24:39

标签: java arrays synchronized

如果我想锁定整个数组,我可以使用synchronized关键字,如下所示:

int arr[];

synchronized void inc(int a, int b){
    arr[a]=arr[a]+b;
}

但我可以只锁定项arr[a],以便其他线程仍然可以同时读/写该数组的其他项吗?

4 个答案:

答案 0 :(得分:6)

也许更合适的结构是AtomicIntegerArray

答案 1 :(得分:3)

不是开箱即用的,但您可以创建一个与int数组大小相同的Object数组,并使用不同的对象填充数组。因此,当您想要锁定int数组中的特定元素时,您可以在相应的索引处锁定该Object:

final Object[] locks = new Object[arr.length]:
for(int i = 0; i < arr.length; i++) {
 locks[i] = new Object();
}

锁定时:执行

synchronized(locks[a]) {
  // do something here
}

答案 2 :(得分:1)

不,数组元素是原始元素,您无法锁定它们。 (如果它们是对象,它也不会有帮助,因为锁定只对可变对象有帮助。你想要锁定数组索引,而不是锁定该索引的内容。)

唯一可能的构造是创建一个唯一引用数组索引并在其上同步的键(或使用Semaphore),但这只有在其他线程访问数组时才有用。同样的方式。

我说更改你的设计,摆脱int数组并使用一个数据结构,让你同步对其元素的访问(List包裹着Collections.synchronizedList())将是一个很好的起点。

答案 3 :(得分:0)

如果这真的是你的瓶颈,完全不同的结构可能更合适。如果你说8个核心,那么他们必须忙碌并且花费大约1/8的时间添加数字以查看严重的争议。如果执行此操作大约是您工作的八分之一,那么您应该将系统设计为不要将其锁定。

假设您需要在多个线程中获取大量值。例如在很长的列表中计算一个数字的出现次数。

每次更新时,您可以拥有一个同步的计数器阵列,并且锁定一个非常昂贵的锁。 (同步化很快但很多,比添加慢得多)

或者你可以让所有的线程都保留自己的总数,最后总结一下。除了你没有使用任何锁之外,最终总数是相同的!