Преимущества runtime.LockOSThread в Голанге
Golang поддерживает LockOSThread()
, чтобы сделать текущий goroutine исключительно привязанным к текущему потоку ОС, и он также может UnlockOSThread()
.
Существуют ли какие-либо варианты использования этой функции?
Ответы
Ответ 1
С моделью Threading Go, вызовы кода C, кода ассемблера или системных вызовов блокируются в том же потоке, что и вызывающий код Go, который управляется планировщиком выполнения Go.
Механизм os.LockOSThread()
в основном полезен, когда Go должен взаимодействовать с некоторой иностранной библиотекой (например, с библиотекой C). Это гарантирует, что несколько последовательных вызовов в эту библиотеку будут выполнены в одном и том же потоке.
Это интересно в нескольких ситуациях:
-
несколько графических библиотек (OS X Cocoa, OpenGL, SDL,...) требуют всех вызовов выполняться в определенном потоке (или в главном потоке в некоторых случаях).
-
некоторые зарубежные библиотеки основаны на средствах локального хранилища (TLS). Они сохраняют некоторый контекст в структуре данных, прикрепленной к потоку. Или некоторые функции API предоставляют результаты, жизненный цикл которых привязан к потоку. Эта концепция используется как в Windows, так и в Unix-подобных системах. Типичным примером является глобальная переменная errno, обычно используемая в библиотеках C для хранения кодов ошибок. В системах, поддерживающих многопоточность, errno обычно определяется как локальная переменная потока.
-
В более общем плане, некоторые зарубежные библиотеки могут использовать идентификатор потока для индексирования/управления внутренними ресурсами.
Ответ 2
runtime.LockOsThread обычно используется для вызова кода C, который требует запуска в основном потоке, например, в графических библиотеках.
Перейти Wiki страница об LockOsThread и пример того, как ее использовать.
Группы Google обсуждение об использовании LockOsThread в SDL.
Ответ 3
Как упомянутый здесь, то, что runtime.LockOSThread
делает, предотвращает запуск любого другого goroutine в том же потоке.
Но обратите внимание, что Go 1.10 (Q1 2018) немного изменит его использование:
Поскольку одно общее использование LockOSThread
и UnlockOSThread
заключается в том, чтобы позволить коду Go надежно модифицировать локальное состояние потока (например, пространства имен Linux или Plan 9), среда выполнения теперь рассматривает заблокированные потоки как непригодные для повторного использования или для создания новых потоков.
Изменено поведение вложенных вызовов LockOSThread
и UnlockOSThread
. Эти функции контролируют, заблокирован ли goroutine для определенного потока операционной системы, так что goroutine работает только в этом потоке, и поток работает только с этим goroutine.
Ранее вызов LockOSThread
более одного раза подряд был эквивалентен вызову один раз, а один UnlockOSThread
всегда разблокировал поток.
Теперь, вызовы гнездятся: если LockOSThread
вызывается несколько раз, UnlockOSThread
нужно вызывать столько же раз, чтобы разблокировать поток.