0

假设我的 java 代码中有 2 个同步方法:

    public class SynchronizedCounter {
    private int c = 0;

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

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

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

假设我有 2 个操作线程:t1 和 t2。如果 t1 正在对 increment() 方法进行操作并在中途进入睡眠状态,则 t2 将由于锁定而无法对 increment() 方法进行操作。我的问题是 t2 是否能够对 decrement() 和 value() 进行操作,或者一旦线程访问其中一个同步方法,与对象关联的所有同步方法都会被锁定?

静态同步方法呢?

4

6 回答 6

5

同步实例方法使用对象实例作为锁。没有两个线程可以同时使用同一个对象进入这些方法。如果您的 t1 和 t2 在同一个对象上操作,则 t2 将被阻塞,直到 t1 释放锁。

对于静态同步方法,锁被放在Class包含方法的类的对象上。

您可以在并发教程中阅读有关锁定的更多信息,但本质上静态方法和非静态方法之间的区别在于被锁定的对象;此类中的方法声明:

class Test {
  synchronized void methodA() { ... }
  static synchronized void methodB() { ... }
}

相当于这里的方法声明:

class Test {
  void methodA() { 
    synchronized (this) {
        ...
    }
  }
  static void methodB() { 
    synchronized (Test.class) {
        ...
    }
  }
}
于 2013-09-30T08:11:16.617 回答
2

documentaction声明:“当一个线程正在为一个对象执行同步方法时,所有其他线程为同一对象块调用同步方法(暂停执行),直到第一个线程完成该对象。”,这几乎可以回答你的问题。

于 2013-09-30T08:12:08.590 回答
1

当您将方法声明为同步时,实例对象将被视为锁。

于 2013-09-30T08:11:17.963 回答
0

对象的所有同步实例方法共享同一个锁,由对象体现。所有静态同步方法共享同一个锁,由类对象体现。

如果需要更细粒度的锁定,则需要使用同步块和单独的锁定对象,即

private Object decrementLock = new Object();
public void decrement() {
    synchronized(decrementLock){
        c--;
    }
}

当然,在这种情况下,这会破坏同步点并导致数据损坏。

于 2013-09-30T08:15:09.037 回答
0

锁与对象相关联,而不与线程相关联。超过 1 个线程可以访问同步方法,但调用方法的对象应该不同。

于 2015-04-24T13:30:37.317 回答
0

同步方法对它们所在类的实例的锁进行操作。简而言之:如果在任何线程中t1休眠,则increment()没有线程可以访问任何synchronized方法。

您的代码也与Java 教程中的示例相同,它也提供了您的答案...

于 2013-09-30T08:11:49.913 回答