简体   繁体   English

为什么这个同步块似乎需要很长时间才能锁定?

[英]Why does it seem to take a long time for this synchronized block to get a lock?

I am new to multi-threading in java, and I have a question some might find trivial. 我是java中的多线程新手,我有一个问题,有些人可能会发现微不足道。

I have to debug a third party piece of code and I need some basic information, to know where to look for the problem because the code is very large. 我必须调试第三方代码,我需要一些基本信息,知道在哪里寻找问题,因为代码非常大。

When the following code runs: 运行以下代码时:

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

I get: 我明白了:

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

Why is taking so long (3816 ms) to get the lock for the object? 为什么需要这么长时间(3816毫秒)才能获得对象的锁定? Where should I look? 我应该在哪里看? For example, I would imagine a possible answer would be to look for code which acquires the lock for "obj" ie block such as: 例如,我想可能的答案是寻找获取“obj”锁定的代码,例如:

synchronized (obj) { ... }

Or is it possible that any modification at the object "obj" without "synchronized" can also lock the object? 或者是否可能在没有“synchronized”的对象“obj”上进行任何修改也可以锁定对象?

If it takes a thread that long to obtain a lock, it's because someone else is currently holding it. 如果获取锁定的线程很长,那是因为其他人正在持有它。

You should look for two things: 你应该找两件事:

  1. Code blocks which synchronize on the same object or on other references to it (known as synchronized statements ) : 在同一对象或对其进行其他引用时synchronize代码块(称为synchronized语句 ):

     synchronized (obj) { ... } 
  2. Synchronized methods within the object itself. 对象本身内的同步方法

    Say obj is of type MyObject , then you should look for methods such as these: 假设objMyObject类型,那么你应该寻找这样的方法:

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

    Because they are essentially the same as 因为它们基本相同

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

    So if a thread is executing obj.myMethod() , threads that want to enter a synchronized (obj) block will have to wait, as they all lock on the same object. 因此,如果一个线程正在执行obj.myMethod() ,那么想要输入synchronized (obj)块的线程将必须等待,因为它们都锁定在同一个对象上。 This, by the way, is the reason why I strongly recommend never using the synchronized method syntax, and always locking over a private (or protected) class member. 顺便说一句,这就是我强烈建议永远不要使用synchronized方法语法,并始终锁定私有(或受保护)类成员的原因。

If another thread is currently executing code within such a block, the current thread will be locked out until the other thread finishes. 如果另一个线程当前正在这样的块中执行代码,则当前线程将被锁定,直到另一个线程完成。

You can use jvisualvm's Threads tab or Jstack to take snapshots of the current execution state of all threads and the locks they're holding. 您可以使用jvisualvm的Threads选项卡Jstack来获取所有线程的当前执行状态及其持有的锁的快照。 If you're on android, see this answer on how to get a thread dump on there. 如果您使用的是android,请参阅答案,了解如何在那里获取线程转储。

The jstack utility that is part of the jdk can help with this. 作为jdk一部分的jstack实用程序可以帮助解决这个问题。 The -l (long listing) option will print all of the locks held by various threads. -l (长列表)选项将打印各种线程持有的所有锁。 If you can catch your program in the midst of the issue then you can find the other thread that is holding the lock. 如果您可以在问题中捕获您的程序,那么您可以找到持有锁的其他线程。 You do this by finding your thread, seeing what condition object it is waiting on, then searching the rest of the stack traces for that condition object. 您可以通过查找线程,查看它正在等待的条件对象,然后搜索该条件对象的其余堆栈跟踪来完成此操作。

This article has more detailed information about how to look at the thread dump. 本文提供了有关如何查看线程转储的更多详细信息。

You need to check the following: 您需要检查以下内容:

  • Are there any method/block in your obj class, which is synchronized on this. 你的obj类中是否有任何方法/块,它们在此同步。 If yes then there must be multiple threads where one is your above code, while other might be using the methods of same obj. 如果是,则必须有多个线程,其中一个是您的上述代码,而其他线程可能正在使用相同obj的方法。
  • Where all you are sharing obj? 所有你在哪里分享obj? If it's shared by multiple classes, then check out who locks on same obj. 如果它由多个类共享,那么检查谁锁定在同一个obj上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM