需要在使用并发 API 时使用同步吗?

huangapple go评论87阅读模式
英文:

Is there a need to use synchronized when using Concurrent APIs

问题

在使用并发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();
        }
    }

}
英文:

Is there a need to use synchronized when working with Concurrent APIs? In other words is there a difference between this

class MessageQueue {

    Queue&lt;String&gt; q = new LinkedList&lt;&gt;();


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

    public String get() {

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

}

this,

class MessageQueue2 {

    Queue&lt;String&gt; q = new ConcurrentLinkedQueue&lt;&gt;();

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

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

}

and this ?

class MessageQueue3 {

    Queue&lt;String&gt; q = new ConcurrentLinkedQueue&lt;&gt;();




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

    public String get() {

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

}

答案1

得分: 1

并发容器可以安全地在多个线程中使用。这意味着修改容器的操作会进行同步,即多个线程修改容器不会使其损坏。因此,对于这种特定用法,#1和#2在功能上是等效的,而#3使用了冗余的同步。

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

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

英文:

Concurrent containers are safe to use from multiple threads. That means operations that modify the container take care of synchronization, i.e. multiple threads modifying the container will not corrupt it. So for this particular usage, #1 and #2 are functionally equivalent, and #3 uses redundant synchronization.

That doesn't mean you can implement any algorithm using a concurrent container and remove synchronization.

If the algorithm involves multiple shared objects or more than one operation on the same object, then you need a synchronized block to enclose all operations even if you use a concurrent container. Without an enclosing synchronized block, other threads may run concurrently and create a race condition, even if the containers are thread-safe.

huangapple
  • 本文由 发表于 2020年7月25日 03:24:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63080266.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定