Люди — высококонкурентный вид, деликатный.
первое знакомство
Первое впечатление от языка Go состоит в том, что он изначально поддерживает параллельное программирование и использует сопрограммы, которые легче, чем потоки.
Разница между процессами, потоками и сопрограммами
- Процесс — это «экземпляр выполнения программы», который действует как объект, распределяющий системные ресурсы. Создание процесса должно выделять полное отдельное адресное пространство. Переключение процессов происходит только в режиме ядра.
- Поток: Поток — это поток выполнения процесса, который независимо выполняет свой собственный программный код.Это наименьшая единица потока выполнения программы и основная единица планирования и диспетчеризации процессора. Процесс может иметь один или несколько потоков.
- Сопрограммы: сопрограммы не являются процессами или потоками, и их выполнение больше похоже на подпрограмму или вызов функции без возвращаемого значения. Параллельные сопрограммы могут быть созданы на уровне языка, а затем написаны для управления ими. Go отдает этот шаг на аутсорсинг, чтобы сделать параллельный запуск сопрограмм менее затратным.
Go реализует простейший параллелизм
for i := 0; i < 10; i++ {
go func(n int) {
fmt.Println(n)
}(i)
}
Проектная практика
В последнее время проекту необходимо одновременно вызывать несколько заданий и ждать завершения этих заданий, прежде чем их можно будет выполнить.
Выполнять задание последовательно
Изначально у нас есть метод, который выполняет задание и выполняет все задания последовательно:
func buildJob(name string) {
...
}
buildJob("A")
buildJob("B")
buildJob("C")
Выполнять задания параллельно
Поскольку все задания могут выполняться одновременно, нет необходимости ждать завершения выполнения предыдущего задания, прежде чем продолжить выполнение других заданий. Мы можем использовать ключевые слова языка Gogo
чтобы быстро включитьgoroutine
, ниже мы будем выполнять три задания одновременно:
go buildJob("A")
go buildJob("B")
go buildJob("C")
дождитесь завершения всех заданий
Как я могу узнать, было ли выполнено каждое задание, здесь вы можете использоватьchannel
общаться и использоватьselect
Проверяем результат выполнения:
func buildJob(ch chan error, name string) {
var err error
... // build job
ch <- err // finnaly, send the result into channel
}
func build() error {
jobCount := 3
errCh := make(err chan error, jobCount)
defer close(errCh) // 关闭 channel
go buildJob(errCh, "A")
go buildJob(errCh, "B")
go buildJob(errCh, "C")
for {
select {
case err := <-ch:
if err != nil {
return err
}
}
jobCount--
if jobCount <= 0 {
break
}
}
return nil
}
проблема найдена
Когда задание А не выполняется,build
метод будетreturn err
выйти и выполнитьclose(errCh)
. Однако в это время другие два задания B и C могут быть не завершены, и результаты также будут отправлены вerrCh
, но с этого времениerrCh
был закрыт, что приведет к выходу программыpanic: send on closed channel
.
оптимизировать код
При отправке данных в канал вы можете использовать второе значение полученных данных, чтобы определить, закрыт ли канал:
func buildJob(ch chan error, name string) {
var err error
... // build job
if _, ok := <-ch; !ok {
return
}
ch <- err // finnaly, send the result into channel
}
func build() error {
jobCount := 3
errCh := make(err chan error, jobCount)
defer close(errCh) // 关闭 channel
go buildJob(errCh, "A")
go buildJob(errCh, "B")
go buildJob(errCh, "C")
for {
select {
case err := <-ch:
if err != nil {
return err
}
}
jobCount--
if jobCount <= 0 {
break
}
}
return nil
}
Суммировать
Параллельное программирование Go, кажется, нуждается только в одном ключевом словеgo
можно бежатьgoroutine
, но на практике все же есть проблемы, с которыми нужно разобраться.
Оригинальная ссылка:Доступно на 8scat.com/posts/code-…