如果我想锁定整个数组,我可以使用synchronized
关键字,如下所示:
int arr[];
synchronized void inc(int a, int b){
arr[a]=arr[a]+b;
}
但我可以只锁定项arr[a]
,以便其他线程仍然可以同时读/写该数组的其他项吗?
答案 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的时间添加数字以查看严重的争议。如果执行此操作大约是您工作的八分之一,那么您应该将系统设计为不要将其锁定。
假设您需要在多个线程中获取大量值。例如在很长的列表中计算一个数字的出现次数。
每次更新时,您可以拥有一个同步的计数器阵列,并且锁定一个非常昂贵的锁。 (同步化很快但很多,比添加慢得多)
或者你可以让所有的线程都保留自己的总数,最后总结一下。除了你没有使用任何锁之外,最终总数是相同的!