我有这个代码:
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/