Golang: разница между потоками и сопрограммами

Go внешний интерфейс
Golang: разница между потоками и сопрограммами

Автор: Линь Гуаньхун / Призраки под рукой

Самородки:Талант /user/178526…

Блог:www.cnblogs.com/linguanh/

Гитхаб:GitHub.com/afan913337456…

Облачная колонка Tencent:cloud.Tencent.com/developer/U…


содержание

  • предисловие
  • сопрограмма
  • Особенности сопрограмм
    • 第 1и第 2точка
    • Пункты 3 и 4 в характеристиках
  • Общее сравнение с потоками

предисловие

Всех с Национальным праздником, прошло почти два месяца с момента последнего поста, а 19 лет подходят к концу. Теперь резюме больше на草稿Вместо того, чтобы отправлять его, на этот раз я подробно поделюсь им в Go.线程和协程的区别及其关系.

сопрограмма

Корутина, английское имяCoroutine. Но на языке Go английское название сопрограммы:gorutine. это часто используется для多任务,Сейчас并发作业. Верно多线程Работа работы.

Хотя в Go нам не нужно писать код, такой как потоки, непосредственно для параллелизма, но сопрограммы Go依赖于线程продолжать.

Давайте посмотрим на их различия ниже.

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

Особенности сопрограмм

Здесь характеристики потока перечислены непосредственно, а затем проанализированы на примере.

  1. Несколько сопрограмм могут управляться одним или несколькими потоками.协程的调度происходит в своем собственном потоке.
  2. Его можно запланировать, и стратегия планирования определяется кодом прикладного уровня, который можно настраивать в широких пределах.
  3. Высокая эффективность исполнения.
  4. Занимайте меньше памяти.

выше第 1и第 2точка

Давайте посмотрим на пример:

func TestGorutine(t *testing.T) {
	runtime.GOMAXPROCS(1)  // 指定最大 P 为 1,从而管理协程最多的线程为 1 个
	wg := sync.WaitGroup{} // 控制等待所有协程都执行完再退出程序
	wg.Add(2)
	// 运行一个协程
	go func() {
		fmt.Println(1)
		fmt.Println(2)
		fmt.Println(3)
		wg.Done()
	}()

	// 运行第二个协程
	go func() {
		fmt.Println(65)
		fmt.Println(66)
		// 设置个睡眠,让该协程执行超时而被挂起,引起超时调度
		time.Sleep(time.Second)
		fmt.Println(67)
		wg.Done()
	}()
	wg.Wait()
}

Приведенный выше фрагмент кода запускает две сопрограммы.После запуска наблюдайте за выводом顺序是交错из. может быть:

65
66
1
2
3
67

Это означает, что в процессе выполнения сопрограммы А вы можете随时中断, чтобы выполнить строку сопрограммы B, сопрограмма B также может быть прервана в процессе выполнения, а затем выполнена сопрограмма A.

Кажется, что выполнение сопрограммы A и сопрограммы B похоже на переключение потоков, но обратите внимание, что и A, и B здесь выполняются в одном потоке. Их планирование — это не переключение потоков, а纯应用态的协程调度.

Что касается приведенного выше кода, зачем указывать следующие две строки кода?

runtime.GOMAXPROCS(1)
time.Sleep(time.Second)

Для этого вам нужно ознакомиться с основами планирования сопрограмм Go. См. мою предыдущую статью об анализе планирования:

Механизм планирования сопрограмм Go

Если не установленоruntime.GOMAXPROCS(1), то программа запустит соответствующее количество P согласно количеству ядер процессора операционной системы, в результате чего получится несколько M, то есть запуск потоков. Тогда сопрограмма в нашей программе будет分配到不同的线程вошел внутрь. Для демонстрации число установлено равным 1, так что все они выделены одному и тому же потоку, сохранены в очереди сопрограммы потока, ожидая выполнения или планирования.

Пункты 3 и 4 в Coroutine Features.

  1. Высокая эффективность исполнения.
  2. Занимайте меньше памяти.

так как协程的调度切换不是线程切换, а управляется самой программой, так что,没有线程切换的开销, По сравнению с многопоточностью, чем больше потоков, тем очевиднее преимущество сопрограмм в производительности. Планирование происходит в режиме приложения, а не в режиме ядра.

Стоимость памяти, использующая память потока, в котором она находится, означает, что память потока может использоваться несколькими сопрограммами.

Планирование второй сопрограммы不需要多线程的锁机制, так как есть только один поток, также不存在同时写变量冲突, поэтому эффективность выполнения намного выше, чем при многопоточности.

Общее сравнение с потоками

точка сравнения нить сопрограмма
хранилище данных Пространство памяти в режиме ядра Как правило, это пространство памяти пользовательского режима, предоставляемое потоком.
переключить действие Операция, наконец, завершается на уровне ядра, и уровень приложения должен вызвать базовую функцию системного вызова, предоставляемую уровнем ядра. Прикладной уровень использует код для простого сохранения и восстановления на месте.
планирование задач Реализуется ядром, упреждающий метод, опирающийся на различные блокировки Это осуществляется специальным планировщиком реализации пользовательского режима. Например, планировщик для go coroutines
уровень голосовой поддержки большинство языков программирования Некоторые языки: Lua, Go, Python...
Спецификация реализации Реализовано в соответствии с современными спецификациями операционной системы Единой спецификации нет. Он реализован разработчиками на уровне приложения и имеет широкие возможности настройки, например, поддерживает только однопоточные потоки. различные стратегии планирования и т. д.

личная реклама

Опубликована моя техническая книга «Практика разработки блокчейн-приложений на Ethereum», которую можно приобрести в Интернете.