首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这个同步块需要很长时间才能获得一个锁?

为什么这个同步块需要很长时间才能获得一个锁?
EN

Stack Overflow用户
提问于 2015-03-02 17:05:06
回答 3查看 2.2K关注 0票数 13

我对java中的多线程很陌生,有些人可能会觉得我有些小问题。

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

当运行以下代码时:

代码语言:javascript
复制
public void method()
{
   long startTime = System.currentTimeMillis();
   synchronized (obj)
   {
      log( "time:" + System.currentTimeMillis() - startTime + " ms" );
      ...
   }
}

我得到:

代码语言:javascript
复制
11:13:12 - time: 3816 ms
...
11:14:14 - time: 0 ms

为什么要花这么长时间(3816 ms)才能得到对象的锁?我该去哪看看?例如,我可以想象一个可能的答案是寻找获取"obj“锁的代码,例如:

代码语言:javascript
复制
synchronized (obj) { ... }

或者,没有“同步”的对象"obj“上的任何修改是否也可以锁定对象?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-03-02 17:17:13

如果需要那么长的线程才能获得锁,那是因为其他人正在持有锁。

你应该寻找两件事:

  1. 代码块,其synchronize位于同一对象或对其的其他引用(称为同步语句)上: 同步(obj) {.}
  2. 对象本身中的同步方法。 假设objMyObject类型的,那么您应该查找这样的方法: 公共类MyObject{公共同步空myMethod() {.}} 因为它们在本质上和 公共类MyObject{公共myMethod() {同步(此){.}} 因此,如果线程正在执行obj.myMethod(),希望进入synchronized (obj)块的线程将不得不等待,因为它们都锁定在同一个对象上。顺便说一下,这就是为什么我强烈建议不要使用同步方法语法,并且总是锁定私有(或受保护的)类成员。

如果另一个线程当前正在此块中执行代码,则当前线程将被锁定,直到其他线程完成为止。

您可以使用jvisualvm的线程选项卡贾斯塔克来快照所有线程的当前执行状态及其所持有的锁。如果您使用的是安卓系统,请参见关于如何在该系统上获得线程转储的答案。

票数 11
EN

Stack Overflow用户

发布于 2015-03-02 17:14:51

作为jdk一部分的J堆栈实用程序可以帮助实现这一点。-l (long清单)选项将打印由不同线程持有的所有锁。如果您可以在问题中捕捉到您的程序,那么您可以找到另一个线程,该线程持有该锁。要做到这一点,您可以找到线程,查看它正在等待的条件对象,然后搜索该条件对象的堆栈跟踪的其余部分。

这个文章有关于如何查看线程转储的更详细信息。

票数 5
EN

Stack Overflow用户

发布于 2015-03-02 17:10:24

您需要检查以下内容:

  • 在obj类中是否有任何方法/块是同步的。如果是,则必须有多个线程,其中一个是上面的代码,而另一个则可能使用相同obj的方法。
  • 你们在哪里分享讣告?如果它被多个类共享,那么检查谁锁在同一个obj上。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28815476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档