简体   繁体   English

是阻塞队列所需的同步块

[英]Are Synchronized Blocks needed for Blocking Queues

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

I know if I use, say a synchronized List, I need to surround it in synchronized blocks to safely use it across threads 我知道是否使用了同步列表,例如,我需要将其围绕在同步块中,以便在线程之间安全地使用它。

Is that the same for Blocking Queues? 阻塞队列是否一样?

No you do not need to surround with synchronized blocks. 不,您不需要包围同步块。

From the JDK javadocs ... JDK javadocs ...

BlockingQueue implementations are thread-safe. BlockingQueue实现是线程安全的。 All queuing methods achieve their effects atomically using internal locks or other forms of concurrency control. 所有排队方法都可以使用内部锁或其他形式的并发控制来原子地实现其效果。 However, the bulk Collection operations addAll, containsAll, retainAll and removeAll are not necessarily performed atomically unless specified otherwise in an implementation. 但是,除非在实现中另外指定,否则批量Collection操作addAll,containsAll,retainAll和removeAll不一定是原子执行的。 So it is possible, for example, for addAll(c) to fail (throwing an exception) after adding only some of the elements in c. 因此,例如,仅在c中添加一些元素之后,addAll(c)可能会失败(引发异常)。

Just want to point out that from my experience the classes in the java.util.concurrent package of the JDK do not need synchronization blocks. 仅想指出,根据我的经验,JDK的java.util.concurrent包中的类不需要同步块。 Those classes manage the concurrency for you and are typically thread-safe. 这些类为您管理并发,通常是线程安全的。 Whether intentional or not, seems like the java.util.concurrent has superseded the need to use synchronization blocks in modern Java code. 不管是否有意, java.util.concurrent似乎都取代了在现代Java代码中使用同步块的需求。

Depends on use case, will explain 2 scenarios where you may need synchronized blocks or dont need it. 取决于用例,将说明两种可能需要同步块或不需要同步块的方案。

  1. Case 1: Not required while using queuing methods eg put, take etc. 情况1:使用排队方法(例如放置,取出等)时不需要

    Why not required is explained here , important line is below: 为什么不要求在这里进行了说明,重要的内容如下:

    BlockingQueue implementations are thread-safe. BlockingQueue实现是线程安全的。 All queuing methods achieve their effects atomically using internal locks or other forms of concurrency control. 所有排队方法都可以使用内部锁或其他形式的并发控制来原子地实现其效果。

  2. Case 2: Required while iterating over blocking queues and most concurrent collections 案例2:在遍历阻塞队列,最并发收集所需

    Since iterator (one example from comments) is weakly consistent, meaning it reflects some but not necessarily all of the changes that have been made to its backing collection since it was created. 由于迭代器 (注释中的一个示例)具有极弱的一致性,这意味着它反映了自其创建以来对其后备集合所做的一些(但不一定是全部)更改。 So if you care about reflecting all changes you need to use synchronized blocks/ Locks while iterating. 因此,如果您关心反映所有更改,则需要在迭代时使用同步块/锁。

You are thinking about synchronization at too low a level. 您正在考虑太低级别的同步。 It doesn't have anything to do with what classes you use. 它与您使用的类无关。 It's about protecting data and objects that are shared between threads. 这是关于保护线程之间共享的数据和对象。

If one thread is able to modify any single data object or group of related data objects while other threads are able to look at or modify the same object(s) at the same time, then you probably need synchronization. 如果一个线程能够修改任何单个数据对象或一组相关数据对象,而其他线程能够同时查看或修改同一对象,则可能需要同步。 The reason is, it often is not possible for one thread to modify data in a meaningful way without temporarily putting the data into an invalid state. 原因是,一个线程通常不可能以有意义的方式修改数据而不将数据暂时置于无效状态。

The purpose of synchronization is to prevent other threads from seeing the invalid state and possibly doing bad things to the same data or to other data as a result. 同步的目的是防止其他线程看到无效状态,从而防止对相同数据或其他数据造成不良影响。


Java's Collections.synchronizedList(...) gives you a way for two or more threads to share a List in such a way that the list itself is safe from being corrupted by the action of the different threads. Java的Collections.synchronizedList(...)为您提供了两个或多个线程共享List的方式, 这样列表本身就可以避免被不同线程的操作破坏。 But, It does not offer any protection for the data objects that are in the List . 但是,它并没有为那些数据对象任何保护List If your application needs that protection, then it's up to you to supply it. 如果您的应用程序需要该保护,则由您自己提供。

If you need the equivalent protection for a queue, you can use any of the several classes that implement java.util.concurrent.BlockingQueue . 如果您需要队列的等效保护,则可以使用实现java.util.concurrent.BlockingQueue的几个类中的任何一个。 But beware! 但是要当心! The same caveat applies. 同样的警告。 The queue itself will be protected from corruption, but the protection does not automatically extend to the objects that your threads pass through the queue. 队列本身将受到保护免于损坏,但是该保护不会自动扩展到线程通过队列传递的对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM