Почему у горутина нет идентичности - PullRequest
0 голосов
/ 25 июня 2018

Я новичок в Голанге и читаю пример из книги gopl.

Раздел 9.8.4 книги Go Programming Language объясняет, почему у Goroutines нет понятия идентичности, доступного для программиста

В Goroutines нет понятия идентичности, которое доступно программисту. Это сделано специально, так как локальное хранилище потоков имеет тенденцию злоупотреблять. Например, на веб-сервере, реализованном на языке с локальным хранилищем потоков, многие функции обычно находят информацию о HTTP-запросе, от имени которого они в данный момент работают, просматривая это хранилище. Однако, как и в случае программ, которые чрезмерно полагаются на глобальные переменные, это может привести к нездоровому «действию на расстоянии», в котором поведение функции определяется не только ее аргументами, но и идентичностью потока в который он запускает. Следовательно, если идентификация потока должна измениться - некоторые рабочие потоки зачисляются, чтобы помочь, скажем, - функция ведет себя странным образом.

и используйте пример веб-сервера для иллюстрации этого момента. Однако мне трудно понять, почему так называемое «действие на расстоянии» является плохой практикой и как это приводит к

функция определяется не только своими аргументами, но и идентификатором потока, в котором она выполняется.

Кто-нибудь может дать объяснение этому (желательно в коротких фрагментах кода)

Любая помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 10 июля 2018

Допустим, у нас есть следующий код:

func doubler(num int) { 
    return num + num
}

doubler(5) вернет 10.go doubler(5) также вернет 10.

Вы можете сделать то же самое с каким-то локальным хранилищем потока, если хотите:

func doubler() { 
    return getThreadLocal("num") + getThreadLocal("num")
}

И мы можем запустить это с чем-токак:

go func() {
    setThreadLocal("num", 10)
    doubler()
}()

Но что яснее?Вариант, который явно передает аргумент num, или вариант, который «волшебным образом» получает это из своего рода локального хранилища потока?

Это то, что подразумевается под «действием на расстоянии».Линия setThreadLocal("num", 10) (которая удалена) влияет на поведение doubler().


Этот пример явно искусственный, но тот же принцип применим к более реальным примерам.Например, в некоторых средах весьма распространено использование локальных потоковых вещей, таких как информация о пользователе или другие «глобальные» переменные.

Вот почему в цитируемом вами абзаце он сравнивается с глобальными переменными: thread-localхранилище - это глобальные переменные, применимые только к текущему потоку.

Когда вы передаете параметры в качестве аргументов, вещи намного яснее определены.Не существует волшебного (часто недокументированного) глобального состояния, о котором вам нужно помнить при отладке или написании тестов.

0 голосов
/ 25 июня 2018

Я рекомендую посмотреть в этом посте пример того, почему кто-то может захотеть получить информацию о текущем потоке / потоке, в котором выполняется функция: stackoverflow - основные потоки в C #

Как указывалось в вопросе, обусловливая поведение функции в соответствии с определенными требованиями к потокам (скорее всего), можно получить хрупкий / подверженный ошибкам код, который трудно отладить.

Я полагаю, что ваш учебник пытается сказать, что функция никогда не должна полагаться на выполнение в определенном потоке, поиск потоков и т. Д., Потому что это может вызвать неожиданное поведение (особенно в API, если это не очевидно для конечному пользователю, что функция должна выполняться в определенном потоке). В Go что-то подобное невозможно просто с помощью языкового дизайна. Поведение goroutine никогда не зависит от потоков или чего-то подобного только потому, что goroutines don't have an identity, как вы говорите правильно.

...