我使用并发hashmap来创建矩阵。它的指数范围为100k。我创建了40个线程。每个线程访问矩阵的那些元素并对其进行修改并将其写回矩阵:
ConcurrentHashMap<Integer, ArrayList<Double>> matrix =
new ConcurrentHashMap<Integer, ArrayList<Double>>(25);
for (Entry(Integer,ArrayList<Double>)) entry: matrix.entrySet())
upDateEntriesOfValue(entry.getValue());
我没有发现它是线程安全的。值经常返回为null,我的程序崩溃了。有没有其他方法使其线程安全。或者这是线程安全的,我在其他一些地方有bug。有一件事是我的程序在单线程模式下不会崩溃。
答案 0 :(得分:11)
iterator
对ConcurrentHashMap
确实是线程安全的。
但是代码中不是线程安全的是你似乎更新的ArrayList<Double>
!您的问题可能来自此数据结构。
您可能希望使用适合您需要的concurrent data structure。
答案 1 :(得分:2)
使用矩阵的贴图效率非常低,而且使用它的方式,它甚至不会特别支持稀疏数组。
我建议你使用double [] [],你可以锁定每一行(如果更好的话就是列)如果矩阵足够小你可能更好只使用一个CPU,因为这可以节省你很多开销。
我建议你不要创建比核心更多的线程。对于CPU密集型任务,使用更多线程可能更慢,而不是更快。
矩阵最大为100k * 50
编辑:根据您正在执行的操作,我会尽量确保您拥有较短的尺寸,以便您可以有效地处理不同线程中的每个长尺寸。
e.g
double[][] matrix = new double[50][100*1000];
for(int i=0;i<matrix.length;i++) {
final double[] line = matrix[i];
executorService.submit(new Runnable() {
public void run() {
synchronized(line) {
processOneLine(line);
}
}
});
}
这允许所有线程并发运行,因为它们不共享任何数据结构。他们还可以有效地访问每个双,因为它们在内存中是连续的并且尽可能有效地存储。即100K双打使用大约800KB,但List<Double>
使用2800KB,每个值可以随机排列在内存中,这意味着你的缓存必须更加努力。
谢谢,但事实上我总共拥有80个核心
要有效地使用80核心,您可能希望将较长的行分成两行或四行,以便您可以保持所有核心繁忙,或者找到一次执行多个操作的方法。
答案 2 :(得分:1)
如果多个线程可以同时在同一个List实例上运行,那么ConcurrentHashMap
对于访问Map是安全的线程,但Lists
服务的需要是thread-safe
所以使用修改时thread-safe
list
。
在你的情况下工作ConcurrentHashMap
是安全的,但是当线程转到ArrayList
时,这不是synchronized
,因此多个线程可以同时访问它,这使得它不是线程安全的。您可以使用synchronized block
在列表