从另一个同步方法调用同步方法是否安全?


80

如果一个同步方法调用另一个同步方法,那么线程安全吗?

void synchronized method1() {
     method2()
}

void synchronized method2() {
}

本文对您有帮助吗,还是您在哪里困惑?kalyanchakravarthy.net/?p=413
詹姆斯·布莱克

是的-假设只在上面给定的上下文中调用method2,您实际上不需要将method2标记为已同步。
debracey 2011年

3
此外,是否是线程安全的还取决于这两种方法中发生的情况。例如,如果它们调用非线程安全列表,则它们可能不是线程安全的,如果某个其他线程可以修改该集合。
詹姆斯·布莱克

作为我可能会想到的一个实际问题的答案:是的,synced关键字使用了递归锁;您可以从另一个同步方法安全地调用同步方法。
Brett Kail

已经有一段时间了,但它仍然是google上的首个热门产品,因此:是的,同一对象上的同步块/方法是可重入的。stackoverflow.com/questions/12219376/reentrant-synchronization
Szocske

Answers:


102

是的,当您将方法标记为时synchronized,您实际上是在这样做:

void method1() {
    synchronized (this) {
        method2()
    }
}

void method2() {
    synchronized (this) {
    }
}

当线程调用从method1进入method2时,它将确保它持有对的锁定this,该锁定已经存在,然后可以通过。

当线程直接进入method1或method2时,它将阻塞直到可以获取锁为止(this),然后进入。

正如詹姆斯·布莱克(James Black)在评论中指出的那样,您必须了解方法主体内部的操作。

private final List<T> data = new ArrayList<T>();

public synchronized void method1() {
    for (T item : data) {
        // ..
    }
}

public void method3() {
    data.clear();
}

突然之间,它不是线程安全的,因为ConcurrentModificationException您将来会因为method3不同步而在使用a ,因此线程A在工作时可以由线程A调用method1


我正在尝试回答一个几乎与此处提出的问题相同的问题。这是2种可能的答案(另外2种可能不会运行),正确吗?C.代码将运行,但存在潜在的死锁情况D.代码将运行良好,因为Java提供了可重入的同步,从而使线程可以多次获取同一锁-----我猜是D,但也许潜在的死锁情况取决于方法主体?

@ user3140993此处的代码没有死锁的机会。method3显示了不安全的线程操作,但是您对可重入同步很了解。
pickypg

6

用同步调用标记的方法是否是另一个同步方法线程安全的。

总的来说,这是不可能的。这取决于方法的作用以及相同和其他类上的其他方法的作用。

但是,我们可以确保不同线程对同一对象的method1和method2的调用不会同时执行。根据什么方法做,这可能足以说,类是线程安全的就这些方法。


1

从Java教程网站http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

  1. 同一对象上的两个同步方法调用不可能交错。当一个线程正在执行对象的同步方法时,所有其他调用同一对象块的同步方法的线程(挂起执行),直到第一个线程用该对象完成。

  2. 当同步方法退出时,它将自动与之前对同一对象的同步方法的任何调用建立先发生关系。这样可以保证对对象状态的更改对所有线程都是可见的

因此,Java将确保如果2个线程正在执行同一方法,则这些方法将不会同时执行,而是一个接一个地执行。

但是您需要注意“活力”问题, http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html

另外,无论您是否不必要地锁定,都会在使用代码的代码中锁定整个对象,如果您的对象仅需要对一个变量的同步访问,则应锁定该变量。


@Stephen Lee-您无法锁定变量。然后,您说synchronized (this.someVar)您正在看的参考位于的对象someVar。区别非常重要。
Stephen C
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.