考虑以下代码:
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();
}
答案 0 :(得分:13)
是的,synchronized
关键字是:
synchronized(this) {
//...
}
因此两种方法都有效地锁定在同一个互斥对象上。如果您希望它们彼此独立(在此示例中这是一个坏主意,因为它们都访问相同的值),请参阅Object locking private class members - best practice? (Java)。
BTW你的SynchronizedCounter
应该实现Runnable
而不是扩展Thread
,因为你将它传递给其他线程的构造函数 - 现在它有点令人困惑。
答案 1 :(得分:6)
锁始终在整个对象上。如果访问synchronized
成员中的任何一个。
在你的第一个例子中,有两个线程争用同一个 counter
对象,你明确开始的那个(在无限循环中调用increment()
方法)和另一个线程是主线程(无限地调用decrement()
)。
在第二个示例中,创建了两个对象counter1
和counter2
。它们将拥有彼此独立的锁。锁定一个对象不会影响其他线程访问其他对象。两个线程(显式线程和主线程)获取对两个不同对象的锁定,因此存在无争用。
答案 2 :(得分:1)
这是否意味着increment()和decrement()方法会等待彼此完成?
NO ,这意味着当一个线程在其中时,没有其他线程能够调用increment()和decrement()。要完成,其他线程无法执行此实例/对象的任何同步方法
您可以从同步的方法中调用任何其他同步方法,而无需锁定同一实例/对象