java - 多级同步java行为

标签 java synchronization

如下例所示,一旦在 call 方法中锁定了某个对象,就不需要其他方法具有 synchronized 关键字。

public class Prac
 { 
    public static void main(String[] args)
    {
      new Prac().call();
    }

    private synchronized void call()
    {
      further();
    }

    private synchronized void further()
    {
      oneMore();
    }

    private synchronized void oneMore()
    {
      // do something
    }
 }

但是,如果我仍然将 synchronized 关键字添加到 furtheronceMore 中,那么 java 会在遇到此类情况时做什么? java会检查是否需要锁吗?或者,由于方法调用位于同一堆栈中,因此它只是继续进行,而不检查是否需要锁,因为已经获取了锁。

注意:我怀疑java在这种情况下会如何表现,我不确定,但我认为它与偏向锁定不同。

最佳答案

事实上,java每次进入synchronized方法时都会检查当前线程是否有锁。

private synchronized void oneMore()
    {
      // do something
    }

这相当于

private void oneMore(){
      synchronized(this){
      // do something
    }
}

但是因为java中的内在锁是可重入的;如果一个线程拥有锁,那么一旦它进入另一个同步块(synchronized block),它就不会重新获取它,如您的示例所示。否则,这将造成死锁。

更新:回答下面的评论。来自 Java 并发实践:

Reentrancy is implemented by associating with each lock an acquisition count 
and an owning thread. When the count is zero, the lock is considered unheld. 
When a thread acquires a previously unheld lock, the JVM records the owner 
and sets the acquisition count to one. If that same thread acquires the lock 
again, the count is incremented, and when the owning thread exits the
synchronized block, the count is decremented. When the count reaches zero, 
the lock is released.

因此,检查是否获取了锁,相当于一个 if 语句(或多或少),判断持有拥有线程的变量是否等于尝试获取锁的线程。

但是,正如您所指出的,私有(private)方法上不需要同步关键字。一般来说,您应该尝试删除不必要的同步,因为这通常会导致性能下降。

关于java - 多级同步java行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27290266/

相关文章:

Java SQL 更新查询不工作

java - Freemarker 将哈希值转换为字符串

java - 静态最终字段的同步 getter

java - 在一个线程添加项目而一个线程删除项目时同步最大值

git - git:如何以编程方式确定是否需要 pull 或 push ?

java - Tree实现java中递归函数调用转换为lambda表达式

java - SimpleDateFormat 解析返回错误值

java - 在 hbase 中,无法识别 dir hdfs ://test/apps/hbase/data/lib, 的 fs 忽略了 java.io.IOException

operating-system - 带测试和集合的有界等待互斥

android - 无法创建/添加帐户@模拟 Android 设备