从另一个同步方法调用同步方法是不是安全?
Posted
技术标签:
【中文标题】从另一个同步方法调用同步方法是不是安全?【英文标题】:Is it safe to call a synchronized method from another synchronized method?从另一个同步方法调用同步方法是否安全? 【发布时间】:2011-08-13 12:10:57 【问题描述】:如果一个同步方法调用另一个同步方法,它是线程安全的吗?
void synchronized method1()
method2()
void synchronized method2()
【问题讨论】:
这篇文章能帮你解答吗,或者你在哪里困惑? kalyanchakravarthy.net/?p=413 是的 - 你实际上不需要将 method2 标记为同步,假设它只在上面给出的上下文中调用。 另外,它是否是线程安全的将取决于这两种方法中发生的情况。例如,如果它们调用非线程安全列表,那么它们可能不是线程安全的,如果其他线程可以修改该集合。 作为我猜测的实际问题的答案:是的,同步关键字使用递归锁;您可以安全地从另一个同步方法调用同步方法。 已经有一段时间了,但它仍然是谷歌的第一个热门,所以:是的,同一个对象上的同步块/方法是可重入的。 ***.com/questions/12219376/reentrant-synchronization 【参考方案1】:是的,当您将方法标记为synchronized
时,您确实是在这样做:
void method1()
synchronized (this)
method2()
void method2()
synchronized (this)
当线程调用从method1进入method2时,它将确保它已经持有this
的锁,然后它可以通过。
当线程直接进入method1或method2时,会阻塞,直到能拿到锁(this
),才会进入。
正如 James Black 在 cmets 中所指出的,您必须清楚自己在方法体内部所做的事情。
private final List<T> data = new ArrayList<T>();
public synchronized void method1()
for (T item : data)
// ..
public void method3()
data.clear();
突然之间它就不是线程安全的了,因为您在未来会看到 ConcurrentModificationException
,因为 method3
是不同步的,因此当线程 B 在 method1
中工作时可能会被线程 A 调用。
【讨论】:
我正在尝试回答一个与此处提出的问题几乎相同的问题。这些是 2 个可能的答案(另外 2 个说它不会运行),哪个是正确的? C. 代码将运行,但存在潜在的死锁情况 D. 代码将运行良好,因为 Java 提供了可重入同步,使线程能够多次获取同一个锁 ----- 我猜是 D,但也许潜在的死锁情况取决于方法体? @user3140993 这里的代码没有死锁的机会。method3
显示了不安全的线程操作,但您对可重入同步有所了解。【参考方案2】:
来自 Java 教程网站http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
同一对象上的同步方法的两次调用不可能交错。当一个线程正在为一个对象执行同步方法时,所有其他为同一对象调用同步方法的线程都会阻塞(暂停执行),直到第一个线程处理完该对象。
当同步方法退出时,它会自动与同一对象的任何后续同步方法调用建立起之前的关系。这保证了对象状态的变化对所有线程都是可见的
所以 Java 会确保如果 2 个线程执行同一个方法,这些方法不会同时执行,而是一个接一个地执行。
但您需要注意 Liveness 问题,http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
还有,无论您是否不必要地锁定,因为在您使用 this 的代码中,它会锁定整个对象,如果您的对象只需要同步访问一个变量,您应该锁定该变量。
【讨论】:
@Stephen Lee - 您无法锁定变量。然后你说synchronized (this.someVar)
你正在查看其引用保存在someVar
中的对象。区别很重要。
一个不锁定这个的例子。 private final Object mSync; synchronized (this.mSync) //some code
【参考方案3】:
一个标有同步的方法调用另一个同步方法线程安全吗。
一般来说,不能说。这取决于方法做什么,以及同一类和其他类上的其他方法做什么。
但是,我们可以确定不同线程对同一对象的方法 1 和方法 2 的调用不会同时执行。根据方法的作用,这可能足以说明该类相对于这些方法是线程安全的。
【讨论】:
以上是关于从另一个同步方法调用同步方法是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章