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 - 无法将 GPS 坐标发送到服务器

android - master details控件在新页面不显示内容

multithreading - FIFO队列的共识数量

objective-c - 使用cocoa的performSelectorOnMainThread数千次的安全性

java - JTextfield 数组帮助

java - 单击提交后如何用数据填充两个实体

java - 为什么我的 JPanel 不显示?

android - 如何以编程方式在 Android 中启用 "Use location?"消息?

java - 尝试转换 yyyy-MM-ddTHH :mm:ss-07:00 to correct time in Android

java - 一个线程写数据不读,多线程读数据不写