12

考虑以下代码:

public class SynchronizedCounter extends Thread {
    private int c = 0;

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

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

    public void run() {
        for(;;)
            increment();
    }
}

static void main(String[] args) {
    SynchronizedCounter counter = new SynchronizedCounter();
    counter.start();
    for(;;)
        counter.decrement();
}

这是否意味着increment()decrement()方法将相互等待完成与否?

编辑: 这不等待?

static void main(String[] args) {
    SynchronizedCounter counter1 = new SynchronizedCounter();
    SynchronizedCounter counter2 = new SynchronizedCounter();
    counter1.start();
    for(;;)
        counter2.decrement();
}
4

3 回答 3

13

是的,synchronized关键字是以下的简写:

synchronized(this) {
  //...
}

所以这两种方法都有效地锁定了同一个互斥对象。如果您希望它们彼此独立(在此示例中这是一个坏主意,因为它们都访问相同的值),请参阅对象锁定私有类成员 - 最佳实践?(爪哇)

顺便说一句,你SynchronizedCounter应该实现Runnable而不是扩展 aThread因为你将它传递给其他线程的构造函数 - 现在它有点令人困惑。

于 2012-05-13T11:45:00.647 回答
6

总是在整个对象上。如果其中任何一个synchronized成员被访问。

在您的第一个示例中,有两个线程争用同一个 counter对象,一个是您显式启动的(它increment()在无限循环中调用该方法),另一个线程是主线程(它decrement()无限地调用该方法)。

在第二个示例中,创建了两个对象,counter1并且counter2. 这些将有自己的彼此独立的锁。锁定一个对象不会影响其他线程访问其他对象。两个线程(显式线程和主线程)获取两个不同对象的锁,因此不存在争用

于 2012-05-13T12:03:24.043 回答
1

这是否意味着 increment() 和 decrement() 方法将相互等待完成与否?

NO,这意味着当一个线程在其中时,没有其他线程将能够调用 increment() 和 decrement() 。完整地说,其他线程无法执行此实例/对象的任何同步方法

您可以从同步方法调用任何其他同步方法,而无需锁定同一实例/对象

于 2012-05-13T18:38:14.630 回答