同步块将仅锁定整个对象或方法?

时间:2017-07-07 06:21:50

标签: java multithreading thread-safety synchronized

我在类中有多个方法,大多数方法都有关键部分(共享数据)。所以我把这些方法做成了同步。假设线程t1正在运行其中一个同步块。同时线程t2可以访问其他方法的关键部分吗?

class Sample{

synchronized public void method1(){

}

synchronized public void method2(){

}

synchronized public void method3(){

}

public void method4(){

}

}

3 个答案:

答案 0 :(得分:6)

synchronized始终锁定对象。如果是同步方法,则对象为this。所以基本上这两种方法都是一样的:

synchronized public void method1() {
  // do something
}

public void method1() {
  synchronized(this){
    // do something
  }
}

只要一个线程锁定了锁定对象,就没有其他线程可以锁定此对象。因此,在您的示例中,同步方法(一,二和三)永远不能同时执行。 method4未同步,因此可以随时访问该对象。

如果您想要更细粒度的锁定,因为method1method2应该是独占的,method3method4可以使用例如:< / p>

class Sample{
  private final Object lock1 = new Object();
  private final Object lock2 = new Object();

  public void method1(){
    synchronized(lock1) {
      // do something
    }
  }
  public void method2(){
    synchronized(lock1) {
      // do something
    }
  }

  public void method3(){
    synchronized(lock2) {
      // do something
    }
  }
  public void method4(){
    synchronized(lock2) {
      // do something
    }
  }
}

您甚至可以使用synchonized(lock)方法来包装需要同步的语句,而不是整个方法:

public void method() {
  // some code
  synchronized(lock) {
    // code that must be synchronized
  }
  // some other code
}

通过这种方法,您可以将锁定持续时间降至最低。

答案 1 :(得分:0)

  • 同一对象的两次同步方法调用不可能进行交错。当一个线程正在为一个对象执行一个synchronized方法时,所有其他线程都会调用同一个对象的同步方法(暂停执行),直到第一个线程完成该对象。

  • 当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立before-before关系。这可以保证所有线程都可以看到对象状态的更改

答案 2 :(得分:0)

在案件中

Sample sample1 = new Sample();

多个线程无法访问

sample1.method1(),sample1.method2(),sample1.method3()

但是多个线程可以同时访问

sample1.method4()

如果我们有2个对象

Sample sample1 = new Sample();
Sample sample2 = new Sample();

多个线程可以并行访问

sample1.method1(),sample2.method1() etc.

所以锁定在对象级别