java - 为什么同步方法在我的情况下不起作用(或者更确切地说我的假设有什么问题)?

标签 java concurrency synchronization

我有这个代码:

import java.util.concurrent.atomic.AtomicLong;

interface Counter {

    public void increment();

    public void decrement();

    public int value();

}

class SynchronizedCounter implements Counter {

    private int c = 0;

    @Override
    public synchronized void increment() {
        c++;
    }

    @Override
    public synchronized void decrement() {
        c--;
    }

    @Override
    public synchronized int value() {
        return c;
    }

}

class UnsynchronizedCounter implements Counter {

    private int c = 0;

    @Override
    public void increment() {
        c++;
    }

    @Override
    public void decrement() {
        c--;
    }

    @Override
    public int value() {
        return c;
    }

}

public class TestProjectApp {

    public static void main(String[] args) {

        AtomicLong unsynchronizedErrors = new AtomicLong();
        AtomicLong synchronizedErrors = new AtomicLong();

        for (int i = 0; i < 1000; i++) {
            Counter c = new UnsynchronizedCounter();
            (new Thread(() -> {
                c.increment();
            })).start();

            (new Thread(() -> {
                if (c.value() != 1) {
                    unsynchronizedErrors.incrementAndGet();
                }
            })).start();
        }

        for (int i = 0; i < 1000; i++) {
            Counter c = new SynchronizedCounter();
            (new Thread(() -> {
                c.increment();
            })).start();

            (new Thread(() -> {
                if (c.value() != 1) {
                    synchronizedErrors.incrementAndGet();
                }
            })).start();
        }

        System.out.println("Unsynchronized errors: " + unsynchronizedErrors);
        System.out.println("Synchronized errors: " + synchronizedErrors);

    }

}

我的程序执行结果是:

Unsynchronized errors: 83
Synchronized errors: 26

我明白为什么会出现不同步错误,但我不明白为什么会出现同步错误。

我的假设是,在第二个循环中,增加同步错误数量的线程必须等待,直到使用 SynchronizedCounter::increment() 方法的线程。我的思维方式有什么问题吗?

编辑:

似乎不需要使这些方法同步,但在第二个线程中使用 Thread::join() 方法就足够了。但我还是不明白为什么它不起作用。

最佳答案

你的假设是错误的。 synchronized 保证方法的执行不会交错,并且它们将具有顺序。您希望线程按特定顺序运行,但您不会以任何方式强制执行该顺序。

在第二个循环中,您希望线程按照创建线程的顺序执行同步方法。但是循环体内会发生什么

    Counter c = new SynchronizedCounter();
    (new Thread(() -> {
        c.increment();
    })).start();

    (new Thread(() -> {
        if (c.value() != 1) {
            synchronizedErrors.incrementAndGet();
        }
    })).start();

是您创建的第二个线程(synchronizedErrors 检查器)在第一个线程(进行递增的那个)。您将此归类为错误,但实际上并没有发生错误。

编辑

解决此问题的最佳方法是在查询计数器状态之前加入所有执行递增/递减操作的线程。

关于java - 为什么同步方法在我的情况下不起作用(或者更确切地说我的假设有什么问题)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33503014/

相关文章:

http - 如何在Golang HTTP服务器中定义全局计数器

google-cloud-firestore - 如何实现自己的后台和手机APP实时同步?

java - Java中的指针和引用变量有什么区别?

java - 在eclipse Java中安装chromedriver

node.js - SailsJS + Waterline 带有 Promise 的并发数据库请求

java - 这个 incrementAndGet 是线程安全的吗?它似乎从缓存中提取对象

java - Eclipse: 'Revert' 和 'Override and Update' 之间的区别

java - 整数除法 : How do you produce a double?

java - 更改双端队列元素

java - 空的 synchronized(this){} 对线程之间的内存可见性有什么意义吗?