【问题标题】:Concurrent HashMap iterator:How safe is it for Threading?并发 HashMap 迭代器:Threading 的安全性如何?
【发布时间】:2012-08-03 07:27:42
【问题描述】:

我使用并发 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 并且我的程序正在崩溃。有没有其他方法可以使其线程安全。或者这是线程安全的,我在其他一些地方有错误。一件事是我的程序在单线程模式下不会崩溃。

【问题讨论】:

    标签: java multithreading thread-safety concurrenthashmap


    【解决方案1】:

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

    但是你的代码中不是线程安全的是ArrayList&lt;Double&gt; 你似乎更新了!您的问题可能来自此数据结构。

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

    【讨论】:

    • 你建议我使用同步数组列表吗?
    • 同步数组列表将起作用,因为它一次只能由一个线程访问。但是根据您添加和读取元素的方式,如果您事先知道大小并想要访问特定索引,您可能想要尝试LinkedBlockingQueue 甚至是 java.util.concurrent.atomic 数组。这主要取决于您的需求。
    • 您是否尝试过从同步数组列表开始?它解决了你的问题吗?
    • 我使用 Atomic Doulbe Array 而不是 gauva 包中的 arraylis 。我仍然遇到同样的问题
    • 那么你的问题来自其他地方。如果遇到困难,请尝试隔离包含问题的代码并发布新问题。
    【解决方案2】:

    对矩阵使用映射确实效率低下,而且你使用它的方式,它甚至不能很好地支持稀疏数组。

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

    我建议您创建的线程数不要超过核心数。对于 CPU 密集型任务,使用更多线程可能会更慢,而不是更快。

    矩阵最大为 100k*50

    编辑:根据您正在执行的操作,我会尽量确保您首先拥有较短的维度,以便您可以有效地在不同的线程中处理每个长维度。

    例如

    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);
              }
           }
       });
    }
    

    这允许所有线程同时运行,因为它们不共享任何数据结构。它们还可以有效地访问每个 double,因为它们在内存中是连续的并且尽可能高效地存储。即 100K 双打使用大约 800KB,但 List&lt;Double&gt; 使用 2800KB 并且每个值都可以在内存中随机排列,这意味着您的缓存必须更加努力地工作。

    谢谢,但实际上我总共有 80 个内核

    为了有效地使用 80 个内核,您可能希望将较长的行分成两到四行,以便让所有内核保持忙碌,或者找到一种方法一次执行多个操作。

    【讨论】:

    • 我有足够的核心。这对我来说不是主要问题。矩阵最大 100k*50
    • 只有 40 个核心的人并不多。我建议你使用Runtime.availableProcessors() 来确保你使用了所有的CPU。
    • 什么型号的机器支持80核。通常它是一个数字,例如 16 个四核或 16 个六核。你有 16 * 5 核吗?
    【解决方案3】:

    ConcurrentHashMap 对 Map 的访问是线程安全的,但提供的 Lists 必须是 thread-safe,如果多个线程可以同时对同一个 List 实例进行操作,那么请使用 thread-safe @987654325 @同时修改。

    在您的情况下,处理ConcurrentHashMap 是安全的,但是当线程转到ArrayList 时,这不是synchronized,因此多个线程可以同时访问它,这使得它不是线程安全的。您可以在列表中执行修改的地方使用synchronized block

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      • 2015-09-19
      相关资源
      最近更新 更多