与多个线程中的数组进行非锁定交互(在Java中)

时间:2017-04-19 14:52:00

标签: java multithreading concurrency thread-safety

我需要从两个线程访问一个字符串数组。它必须非常快速且线程安全。我不想使用锁,我可以用什么方法来制作无锁的线程安全的字符串数组?我需要一个Java的食谱。

2 个答案:

答案 0 :(得分:1)

根据定义,争用线程共享的内存可用的唯一线程安全写入是由CPU中的原子指令提供的操作。这与Java无关(至少,几乎所有时间),但值得注意的是,并发环境中没有锁的写入是可能的。

所以,这就是说,如果你想写入数组,你可能需要锁定。锁是解决一般问题的方法。

但是,只要它们只是从数组中读取,您就可以愉快地在多个线程之间共享数组而不会出现问题。因此,如果您的数组是不可变的(或者任何其他对象),那么由于没有争用的机会,它将是线程安全的。

所以,让我们假设你想从两个不同的线程写入数组,但是你担心争用。也许每个线程都想记录大量数据。这个问题有几种不同的解决方案:我将尝试解释一些问题。这并非详尽无遗,因为并发是一个难以解决的问题,虽然有一些常见的方法,但答案往往取决于具体情况。

  1. 最简单的方法
  2. 在写入数组时,只需对数组使用锁定,看看它是如何执行的。也许你现在不需要担心性能问题。

    1. 使用生产者/消费者方法
    2. 不是让两个线程写入同一个数组,而是让每个线程都生成"值(可能将它们放在不同的线程安全队列中)并让另一个线程负责"消费"这些值(从队列中删除它们并将它们放入数组中)。

      如果订单很重要,这种方法实施起来可能很棘手。但是你使用的是并发性,所以无论如何,排序都是非常不确定的。

      1. 分批写作
      2. 这里的想法是,您要将每个线程中要放入数组的值存储在其自己的临时批量值中。当批次达到足够大的大小时,线程将锁定数组并写入整个批次。

        1. 写入数组的不同部分
        2. 如果您知道数据的大小,则可以通过简单地不允许线程写入相同的索引范围来避免争用。您将数组除以线程数。每个线程在创建时都会被赋予数组的起始索引。

          此选项可能符合您的要求(无锁,线程安全)。

答案 1 :(得分:0)

如何使用内置的Collections.synchronizedList