Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从另一个同步方法调用同步方法是否安全?_Java_Thread Safety - Fatal编程技术网

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

Java 从另一个同步方法调用同步方法是否安全?,java,thread-safety,Java,Thread Safety,如果一个同步方法调用另一个同步方法,它是线程安全的吗 void synchronized method1() { method2() } void synchronized method2() { } 是的,当您将方法标记为“已同步”,那么您实际上是在这样做: void method1() { synchronized (this) { method2() } } void method2() { synchronized (this) {

如果一个同步方法调用另一个同步方法,它是线程安全的吗

void synchronized method1() {
     method2()
}

void synchronized method2() {
}

是的,当您将方法标记为“已同步”,那么您实际上是在这样做:

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

void method2() {
    synchronized (this) {
    }
}
当线程调用从method1进入method2时,它将确保它持有对
this
的锁,它将已经持有该锁,然后它可以通过

当线程直接进入method1或method2时,它将阻塞,直到它能够获得锁(
this
),然后它将进入

正如jamesblack在评论中所指出的,您必须知道您在方法体内部所做的事情

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

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

public void method3() {
    data.clear();
}
private final List data=new ArrayList();
公共同步的void方法1(){
对于(T项:数据){
// ..
}
}
公开作废方法3(){
data.clear();
}

突然之间,它不是线程安全的,因为您在将来看到一个
ConcurrentModificationException
,因为
method3
是不同步的,因此当线程B在Java教程站点的
method1
中工作时,线程a可以调用它

  • 同一对象上的两个同步方法调用不可能交错。当一个线程为一个对象执行同步方法时,调用同一对象块的同步方法的所有其他线程(暂停执行),直到第一个线程对该对象执行完毕

  • 当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立“发生在之前”关系。这保证了对对象状态的更改对所有线程都是可见的

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

    但是你需要意识到活力的问题

    以及是否不必要地锁定,因为在您使用的代码中,这个,它锁定了整个对象,如果您的对象只需要同步访问一个变量,您应该锁定该变量

    标记为synchronized call的方法是线程安全的另一个synchronized方法

    一般来说,这是不可能说的。这取决于这些方法做什么,以及同一类和其他类上的其他方法做什么


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

    本文是否有助于回答这个问题,或者您在哪里感到困惑?是-假设method2仅在上面给出的上下文中调用,那么实际上不需要将其标记为synchronized。此外,它是否线程安全将取决于这两个方法中发生的情况。例如,如果它们调用非线程安全列表,那么如果其他线程可以修改该集合,它们可能就不是线程安全的;你可以安全地从另一个同步方法调用一个同步方法。虽然已经有一段时间了,但它仍然是google上第一个成功的方法,所以:是的,同一对象上的同步块/方法是可重入的@Stephen Lee-无法锁定变量。然后说
    synchronized(this.someVar)
    您正在查看其引用保存在
    someVar
    中的对象。区别是非常重要的。我试图回答一个与这里所问问题几乎相同的问题。这是两个可能的答案(另外两个说它不会运行),哪一个是正确的?C.代码将运行,但存在潜在的死锁情况D.代码将运行良好,因为Java提供可重入同步,使线程能够多次获取相同的锁------我猜是D,但是可能的死锁情况取决于方法体?@user3140993这里的代码没有死锁的可能<代码>方法3显示了不安全的线程操作,但您对可重入同步非常了解。