是阻塞队列所需的同步块

时间:2019-03-24 14:17:43

标签: java multithreading parallel-processing

public BlockingQueue<Message> Queue;
Queue = new LinkedBlockingQueue<>();

我知道是否使用了同步列表,我需要将其围绕在同步块中,以便在线程之间安全地使用它

阻塞队列是否一样?

3 个答案:

答案 0 :(得分:2)

否,您不需要包围同步块。

JDK javadocs ...

  

BlockingQueue实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来原子地实现其效果。但是,除非在实现中另外指定,否则批量Collection操作addAll,containsAll,retainAll和removeAll不一定是原子执行的。因此,例如,仅在c中添加一些元素之后,addAll(c)可能会失败(引发异常)。

仅需指出,根据我的经验,JDK的java.util.concurrent包中的类不需要同步块。这些类为您管理并发,通常是线程安全的。无论是否有意,java.util.concurrent似乎已取代了在现代Java代码中使用同步块的需求。

答案 1 :(得分:1)

根据用例,将说明两种可能需要同步块或不需要同步块的场景。

  1. 情况1:不需要,例如使用排队方法放,拿等。

    为什么不需要here的解释,重要的一行如下:

      

    BlockingQueue实现是线程安全的。所有排队方法   使用内部锁或其他形式原子地实现其效果   并发控制。

  2. 情况2:必需,同时遍历阻塞队列和大多数并发集合

    由于iterator(注释中的一个例子)的一致性很弱,这意味着它反映了自其创建以来对其后备集合所做的一些(但不一定是全部)更改。因此,如果您关心反映所有更改,则需要在迭代时使用同步块/锁。

答案 2 :(得分:1)

您正在考虑将同步级别设置得太低。它与您使用的类无关。这是关于保护线程之间共享的数据和对象。

如果一个线程能够修改任何单个数据对象或一组相关数据对象,而其他线程能够同时查看或修改同一对象,则可能需要同步。原因是,在没有临时将数据置于无效状态的情况下,一个线程通常不可能以有意义的方式修改数据。

同步的目的是防止其他线程看到无效状态,并因此可能对相同数据或其他数据造成不良影响。


Java的Collections.synchronizedList(...)为您提供了两个或多个线程共享List的方式,以使列表本身不会受到以下行为的破坏:不同的线程。但是,它对List的数据对象不提供任何保护。如果您的应用程序需要该保护,则由您自己提供。

如果您需要队列的等效保护,则可以使用实现java.util.concurrent.BlockingQueue的多个类中的任何一个。但是要当心!同样的警告。队列本身将受到保护,以防损坏,但是保护不会自动扩展到线程通过队列传递的对象。