java - 为什么这个synchronized block 好像要很久才能拿到锁?

标签 java android multithreading synchronized

我是 Java 多线程的新手,我有一个问题可能有些人觉得微不足道。

我必须调试第三方代码,我需要一些基本信息,以便知道在哪里查找问题,因为代码非常大。

当以下代码运行时:

public void method()
{
   long startTime = System.currentTimeMillis();
   synchronized (obj)
   {
      log( "time:" + System.currentTimeMillis() - startTime + " ms" );
      ...
   }
}

我得到:

11:13:12 - time: 3816 ms
...
11:14:14 - time: 0 ms

为什么要花这么长时间(3816 毫秒)来获取对象的锁? 我应该在哪里看?例如,我想一个可能的答案是寻找获取“obj”锁的代码,即 block ,例如:

synchronized (obj) { ... }

或者是否有可能在没有“synchronized”的情况下对对象“obj”的任何修改也可以锁定该对象?

最佳答案

如果一个线程需要很长时间才能获得锁,那是因为其他人当前正在持有它。

你应该寻找两件事:

  1. 在同一对象或对它的其他引用上同步的代码块(称为synchronized statements):

    synchronized (obj) {
     ... 
    }
    
  2. Synchronized methods在对象本身内。

    假设 objMyObject 类型,那么您应该寻找如下方法:

    public class MyObject{
        public synchronized void myMethod() {
         ...
        }
    }
    

    因为它们本质上是一样的

    public class MyObject{
        public void myMethod() {
            synchronized (this) {
             ...
            }
        }
    }
    

    因此,如果线程正在执行 obj.myMethod(),想要进入 synchronized (obj) block 的线程将不得不等待,因为它们都锁定在同一个对象。顺便说一句,这就是为什么我强烈建议永远不要使用同步方法语法,并且始终锁定私有(private)(或 protected )类成员的原因。

如果另一个线程当前正在执行此类 block 中的代码,则当前线程将被锁定,直到另一个线程完成。

您可以使用 jvisualvm's Threads tabJstack获取所有线程的当前执行状态和它们持有的锁的快照。如果您使用的是 Android,请参阅 this回答如何在那里获取线程转储。

关于java - 为什么这个synchronized block 好像要很久才能拿到锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28815476/

相关文章:

java - 我如何在我的数据库中计算这些变量?

java - 使用方程内部的开关或赋值

java - 如何在android中使用TextWatcher进行查询?

c# - 数小时后 RAM 密集型 C# 进程变慢

java - 无法添加或更新子行 : a foreign key constraint fails - Bidirectional mapping in hibernate

java - 主分片未激活或未分配是已知节点?

android - Slidingdrawer 切换图标不可见

android - 未定义不是 React Native 项目中的函数

带有 Urllib2 问题的 Python 多线程

java - 如何安全地将线程生命周期绑定(bind)在一起,涉及 SQLite