В чем разница между многопоточностью Go и потоками pthread или Java? - PullRequest
31 голосов
/ 16 ноября 2009

В чем разница между многопоточным подходом Go и другими подходами, такими как pthread, boost :: thread или Java Threads?

Ответы [ 4 ]

24 голосов
/ 16 ноября 2009

Цитируется из Учебное пособие 3-го дня <- прочитайте это для получения дополнительной информации. </p>

Goroutines мультиплексируются по мере необходимости на системные потоки. Когда горутин выполняет системный вызов блокировки, нет другие программы заблокированы.

Мы сделаем то же самое для процессора в какой-то момент, но пока если вы хотите параллелизма на уровне пользователя вы должен установить $ GOMAXPROCS. или позвоните по телефону runtime.GOMAXPROCS (п).

Программа не обязательно соответствует потоку ОС. У него может быть меньший начальный размер стека, и стек будет расти по мере необходимости.

При необходимости можно объединить несколько гороитинов в одну нить.

Что еще более важно, концепция, изложенная выше, заключается в том, что программа - это последовательная программа, которая может блокировать себя, но не блокировать другие программы.

В gccgo реализованы функции gthgo в виде pthreads, поэтому они также могут быть идентичны потоку ОС. Он разделяет концепцию потока ОС и наше представление о многопоточности при программировании.

14 голосов
/ 18 ноября 2009

В эталонных компиляторах (5g / 6g / 8g) главный планировщик ( src / pkg / runtime / proc.c ) создает N потоков ОС, где N контролируется runtime.GOMAXPROCS (n ) (по умолчанию 1). Каждый поток планировщика вытаскивает новую программу из основного списка и запускает ее. Программа (ы) будут продолжать выполняться до тех пор, пока не будет выполнен системный вызов (например, printf) или не будет выполнена операция на канале, после чего планировщик захватит следующую программу и выполнит ее с того момента, на котором он остановился (см. gosched () вызывает в src / pkg / runtime / chan.c ).

Планирование для всех намерений и целей осуществляется с помощью сопрограмм . Та же самая функциональность может быть написана на простом C с использованием setjmp () и longjmp (), Go (и других языков, которые реализуют легкие / зеленые потоки) просто автоматизируют процесс для вас.

Преимущество легких потоков заключается в том, что это все пользовательское пространство, поэтому создание «потока» очень дешево (выделяет небольшой стек по умолчанию) и может быть очень эффективным из-за внутренней структуры взаимодействия потоков друг с другом. Недостатком является то, что они не являются настоящими потоками, что означает, что один легкий поток может блокировать всю программу, даже если кажется, что все потоки должны работать одновременно.

13 голосов
/ 16 ноября 2009

IMO, что делает многопоточность в Go привлекательной, это средства связи: в отличие от pthread, где нужно создать инфраструктуру связи (мьютекс, очереди и т. Д.), В Go он доступен по умолчанию в удобной форме.

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

5 голосов
/ 31 января 2013

Как указывалось в предыдущих ответах, подпрограммы go не обязательно соответствуют системным потокам, однако я нашел следующее полезное, если вам необходимо повысить производительность многопоточности прямо сейчас:

Текущая реализация среды выполнения Go не будет распараллеливать этот код по умолчанию. Он выделяет только одно ядро ​​для обработки на уровне пользователя. В системных вызовах может быть заблокировано произвольное количество подпрограмм, но по умолчанию только пользователь может выполнять код уровня пользователя в любое время. Он должен быть умнее и однажды он будет умнее , но до тех пор, пока он не станет , если вам нужен параллелизм ЦП, вы должны указать во время выполнения, сколько программ вы хотите выполнить одновременно . Есть два способа сделать это. Либо запустите задание с переменной среды GOMAXPROCS, для которой задано количество ядер для использования, либо импортируйте пакет времени выполнения и вызовите runtime.GOMAXPROCS (NCPU). Полезным значением может быть runtime.NumCPU (), которое сообщает количество логических процессоров на локальном компьютере. Опять же, ожидается, что это требование будет отменено по мере улучшения планирования и времени выполнения.

источник цитаты

Пример программы, которая максимально использует мой процессор i5, таков (использует все 4 ядра на 100% в htop):

package main


import (
    "fmt"
    "time"
    "runtime"
)


func main() {
    runtime.GOMAXPROCS(4) // Set the maximum number of threads/processes

    d := make(chan string)
    go boring("boring!", d, 1)
    go boring("boring!", d, 2)
    go boring("boring!", d, 3)
    go boring("boring!", d, 4)

    for i := 0; i < 10; i++ {
        time.Sleep(time.Second);
    }

    fmt.Println("You're boring; I'm leaving.")
}

func boring(msg string, c chan string, id int) {
    for i := 0; ; i++ {

    }
}

Теперь это на самом деле ничего не делает, но посмотрим, насколько коротко / просто / просто по сравнению с написанием многопоточных приложений на других языках, таких как Java.

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