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

时间:2015-11-03 15:31:55

标签: 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()方法就足够了。但我仍然不明白为什么它没有奏效。

1 个答案:

答案 0 :(得分:2)

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

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

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

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

您创建的{strong>第二 ThreadsynchronizedErrors检查程序)是在第一个之前运行的join(执行递增的那个) )。您将此归类为错误,但没有发生错误。

修改

解决此问题的最佳方法是 if(condition){ some.changeLabel1(); }else{ some.changeLabel2(); } 在查询计数器状态之前进行递增/递减的所有线程。