2012-08-03 38 views
4

我用并发散列表来创建一个矩阵。它的指数范围为100k。我创建了40个线程。每个线程访问矩阵和修改的该和这些元素写回矩阵为:并发HashMap迭代器:线程的安全性如何?

ConcurrentHashMap<Integer, ArrayList<Double>> matrix = 
    new ConcurrentHashMap<Integer, ArrayList<Double>>(25); 

for (Entry(Integer,ArrayList<Double>)) entry: matrix.entrySet()) 
    upDateEntriesOfValue(entry.getValue());  

我没有发现它线程安全的。值经常返回为空,我的程序崩溃。是否有任何其他方式使它线程安全。或者这是线程安全的,我有一些其他地方的错误。有一件事是我的程序不会在单线程模式下崩溃。

回答

11

iterator确实对于ConcurrentHashMap是线程安全的。

但是,代码中不是线程安全的是您似乎更新的ArrayList<Double>!你的问题可能来自这个数据结构。

您可能需要使用适合您需要的concurrent data structure

+0

你是否建议我使用synchronized Arrayist? – thetna 2012-08-03 07:49:30

+0

同步arraylist将工作,因为它一次只能由一个线程访问。但是,根据添加和读取元素的方式,如果您事先知道大小并希望访问特定索引,则可能需要尝试“LinkedBlockingQueue”或甚至一个java.util.concurrent.atomic数组。它主要取决于你的需求。 – 2012-08-03 08:04:52

+0

您是否尝试使用同步数组列表开始?它解决了你的问题吗? – 2012-08-05 11:01:58

1

ConcurrentHashMap将线程安全的访问到地图,但Lists担任了需要被thread-safe,如果多个线程可以在同一个List实例同时运行这么使用thread-safelist而修改。

在你的情况上ConcurrentHashMap工作被踩安全的,但是当线程去ArrayList这不是​​,因此多个线程可以同时访问它,这使得它的非线程安全的。你可以使用synchronized block你在列表中进行修改的地方

2

对矩阵使用映射效率非常低,而且你使用它的方式,它甚至不会支持稀疏矩阵。

我建议你使用double [] []来锁定每一行(或列,如果这样更好的话)如果矩阵足够小,你可能会更好地使用一个CPU,因为这可以为你节省很多的开销。

我会建议你创建没有更多的线程比你有核心。对于CPU密集型任务,使用更多线程可能会更慢,而不是更快。

Matrix是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核高效,你可能想打破长行中两个或四个这样你就可以把所有的核心忙,或者发现一次执行多个操作的方式。

+0

我有足够的内核。这对我来说不是主要问题。矩阵最大为** 100k * 50 ** – thetna 2012-08-03 07:44:21

+0

并不是很多人都有40个内核。我建议你使用'Runtime.availableProcessors()'来确保你使用了所有的cpus。 – 2012-08-03 07:46:30

+0

谢谢,但实际上我总共有80个核心。 – thetna 2012-08-03 07:48:53