Я думаю, что излишне объяснять, как это работает, мы должны использовать только один из методов lock () или tryLock ():
Если у вашего потока есть несколько задач, некоторые из которых не зависят от блокировки, вам следует использовать tryLock (). Если все задачи, которые должен выполнять ваш поток, зависят от блокировки, то вам следует использовать lock ().
То есть вы должны использовать tryLock () over lock (), когда поток имеет или может получить дополнительную работу, независимую от получения блокировки.
----- Дополнительно:
Допустим, у вас есть четыре задачи, с 1 по 3, которые выполняются пулом потоков с двумя рабочими потоками, A и B. Задачи 1 и 2 совместно используют ресурс, к которому должен обращаться один поток за раз, чтобы предотвратить коррупция.
Теперь, если вы просто заблокируете без пробной версии, вы можете попасть в следующую ситуацию:
Тема A запускает задание 1;
Поток A получает блокировку ресурса;
- Тема B запускает задачу 2;
- Нить B пытается получить блокировку, но блокируется (спит);
- Нить А завершает задание 1, освобождая замок;
- Нить B просыпается, но нить A еще не переключилась;
- Тема A запускает задание 3;
- Поток B пытается снова получить блокировку;
- Поток B получает блокировку и завершает задачу 2;
- Тема А завершает задание 3.
Обратите внимание, что lock () приостанавливает поток до тех пор, пока блокировка не будет снята, поэтому поток B совершенно бесполезен, пока поток A не снимет блокировку. Поток B мог бы запустить задачу 3 вместо ожидания блокировки и завершить ее тем временем.
Алгоритм, использующий try-lock, может выполняться следующим образом:
- Тема A запускает задание 1;
- Поток A тестирует и получает блокировку;
- Тема B запускает задачу 2;
- Поток B тестирует блокировку, пропуская задачу 2;
- Тема B запускает задание 3;
- Нить А завершает задание 1, освобождая блокировку;
- Тема A запускает задачу 2;
- Тема B завершает задание 3;
- Нет больше задач, поэтому нить B спит;
- Нить А завершает задание 2, снимая блокировку.
Обратите внимание, что tryLock () не приостанавливает вызывающий поток, поэтому задача блокировки может быть пропущена, и поток B вместо этого выполняет задачу блокировки. Если задачи 1 и 2 были длинными, и было несколько других коротких неблокирующих задач, все они могли бы быть завершены до завершения задачи 1 или запуска задачи 2.
Конечно, реализация пулов потоков и управление задачами немного сложнее, чем простая блокировка: задачи могут быть приостановлены и возвращены в пул; и спящие незанятые нити должны быть разбужены при снятии любых блокировок.
Стоит потрудиться, если у вас есть много неблокирующих задач (или, по крайней мере, не блокировать одну и ту же блокировку) вместе с некоторыми блокирующими задачами, но если все задачи блокируются на одном и том же ресурсе, это даже не стоит Реализация многопоточности в первую очередь.