Intereting Posts
Как получить исходный файл из файла apk Невозможно разрешить метод startActivity () Удалить синий экран Android: AsyncTask, как можно обновить шаг ProgressDialog Android: требуется запись микрофонного входа Как создать общий каталог с доступом для чтения и записи ко всем приложениям в Android? При использовании scrollTo ListView не обновляется, но когда ручная прокрутка обновляется Как скомпилировать C-программу для Genymotion (Android x86) Сообщение об ошибке Logcat – Попытка уничтожить барьер с ненулевым счетом Уровень безопасности для Android в edittext Как использовать DrawerLayout для отображения на панели ActionBar / Toolbar и в строке состояния? В пользовательском представлении отсутствует конструктор, используемый инструментами для адаптера Android-векторное приложение: srcCompat не показывает изображения Активность Android как диалог Как решить ошибку сборки для продукта, когда ссылочный, но ненужный источник / ресурс не найден?

Почему, похоже, для этого синхронизированного блока требуется много времени, чтобы получить блокировку?

Я новичок в многопоточности в 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», т.е. блок, такой как:

 synchronized (obj) { ... } 

Или возможно, что любая модификация объекта «obj» без «синхронизированного» может также блокировать объект?

Solutions Collecting From Web of "Почему, похоже, для этого синхронизированного блока требуется много времени, чтобы получить блокировку?"

Если для получения блокировки требуется поток, который длится долго, это происходит потому, что кто-то еще удерживает его.

Вы должны искать две вещи:

  1. Блоки кода, которые synchronize на одном и том же объекте или на других ссылках на него (так называемые синхронизированные операторы ):

     synchronized (obj) { ... } 
  2. Синхронизированные методы внутри самого объекта.

    Скажем, obj имеет тип MyObject , тогда вы должны искать такие методы, как:

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

    Потому что они по существу те же, что и

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

    Поэтому, если поток выполняет obj.myMethod() , потоки, которые хотят ввести synchronized (obj) блок, должны будут ждать, поскольку все они блокируются на одном и том же объекте. Это, кстати, является причиной, по которой я настоятельно рекомендую никогда не использовать синхронный синтаксис метода и всегда блокировать доступ к частному (или защищенному) классу.

Если другой поток в настоящее время выполняет код внутри такого блока, текущий поток будет заблокирован до тех пор, пока не закончится другой поток.

Вы можете использовать вкладку «Темы» jvisualvm или Jstack, чтобы делать снимки текущего состояния выполнения всех потоков и блокировок, которые они удерживают. Если вы находитесь в android, см. Этот ответ о том, как получить дамп потока.

Утилита jstack, которая является частью jdk, может помочь в этом. Опция -l (длинный список) будет печатать все блокировки, принадлежащие различным потокам. Если вы можете поймать свою программу посреди проблемы, вы можете найти другой поток, удерживающий блокировку. Вы делаете это, находя свой поток, видя, какой объект условия он ожидает, затем просматривая остальные трассировки стека для этого объекта условия.

В этой статье содержится более подробная информация о том, как посмотреть дамп потока.

Вам необходимо проверить следующее:

  • Есть ли какой-либо метод / блок в вашем классе obj, который синхронизируется по этому вопросу. Если да, то должно быть несколько потоков, где один из них – ваш вышеприведенный код, в то время как другие могут использовать методы того же obj.
  • Где все вы обмениваетесь obj? Если он используется несколькими классами, то проверьте, кто блокирует его на том же объекте.