【问题标题】:Is there a need to use synchronized when using Concurrent APIs使用并发 API 时是否需要使用同步
【发布时间】:2020-07-24 19:24:49
【问题描述】:

在使用并发 API 时是否需要使用 synchronized?也就是说这有区别吗

class MessageQueue {

    Queue<String> q = new LinkedList<>();


    public void post(String msg) {
        synchronized (q) {
            q.add(msg);
        }
    }

    public String get() {

        synchronized (q) {
            return q.poll();
        }
    }

}

这个,

class MessageQueue2 {

    Queue<String> q = new ConcurrentLinkedQueue<>();

    public void post(String msg) {
            q.add(msg);
    }

    public String get() {
            return q.poll();
    }

}

还有这个?

class MessageQueue3 {

    Queue<String> q = new ConcurrentLinkedQueue<>();




    public void post(String msg) {
        synchronized (q) {
            q.add(msg);
        }
    }

    public String get() {

        synchronized (q) {
            return q.poll();
        }
    }

}

【问题讨论】:

  • 队列的读写不必同步。如果您想用新的 Queue 对象替换 Queue 对象,您只需要同步即可。

标签: java multithreading java.util.concurrent


【解决方案1】:

并发容器可以安全地从多个线程中使用。这意味着修改容器的操作负责同步,即多个线程修改容器不会破坏它。所以对于这个特定的用法,#1 和#2 在功能上是等效的,而#3 使用冗余同步。

这并不意味着您可以使用并发容器实现任何算法并移除同步。

如果算法涉及多个共享对象或对同一对象的多个操作,那么即使使用并发容器,您也需要一个同步块来封装所有操作。如果没有封闭的同步块,其他线程可能会并发运行并创建竞争条件,即使容器是线程安全的。

【讨论】:

  • 同意。我理解同步的更广泛的必要性(比如简单的通知)。问题是关于在 ConcurrencyAPI 上使用 synchronized 的必要性,我认为您说这是多余的。
  • 对于这种特殊情况,是的,它是多余的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-28
  • 2023-04-04
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 2021-03-31
相关资源
最近更新 更多