Как в Go можно использовать многопоточность?

Пользователь

от porter.kertzmann , в категории: Вопросы от знатоков , год назад

Как в Go можно использовать многопоточность?

Facebook Vk Ok Twitter LinkedIn Telegram Whatsapp Pocket

2 ответа

Пользователь

от laurine_beahan , год назад

@porter.kertzmann 

Go был разработан с учетом многопоточности, и в языке есть много встроенных средств для создания и управления горутинами (goroutine), которые позволяют выполнять задачи параллельно.


В Go каждая горутина представляет собой легковесный поток выполнения, которым управляет планировщик горутин (goroutine scheduler). Каждая горутина запускается с помощью ключевого слова go, и ее выполнение происходит параллельно с выполнением других горутин.


Пример использования многопоточности в Go:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    // первая горутина
    go func() {
        defer wg.Done()
        fmt.Println("Первая горутина")
    }()

    // вторая горутина
    go func() {
        defer wg.Done()
        fmt.Println("Вторая горутина")
    }()

    wg.Wait()
    fmt.Println("Все горутины завершились")
}


В этом примере создаются две горутины, каждая из которых выводит сообщение в консоль. Функция sync.WaitGroup используется для ожидания завершения обеих горутин.


Также в Go есть механизмы для обеспечения безопасности при работе с общими ресурсами в многопоточной среде, такие как мьютексы (mutex) и каналы (channel). Мьютексы позволяют блокировать доступ к общим ресурсам, пока они не освободятся, а каналы предоставляют способ взаимодействия между горутинами.

Пользователь

от ike_lowe , 7 месяцев назад

@porter.kertzmann 

Например, вот как можно использовать мьютексы и каналы в Go:


Мьютексы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main

import (
    "fmt"
    "sync"
)

var counter int
var mutex sync.Mutex

func increment() {
    mutex.Lock()
    defer mutex.Unlock()
    counter++
}

func decrement() {
    mutex.Lock()
    defer mutex.Unlock()
    counter--
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        defer wg.Done()
        for i := 0; i < 1000; i++ {
            increment()
        }
    }()

    go func() {
        defer wg.Done()
        for i := 0; i < 1000; i++ {
            decrement()
        }
    }()

    wg.Wait()
    fmt.Println("Counter:", counter)
}


В этом примере создаются две горутины, одна увеличивает счетчик, а другая уменьшает его. Они оба используют мьютекс, чтобы блокировать доступ к общей переменной counter и гарантировать, что значение не будет модифицировано параллельно. В результате получаем значение счетчика равное 0.


Каналы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import "fmt"

func sum(numbers []int, c chan<- int) {
    sum := 0
    for _, num := range numbers {
        sum += num
    }
    c <- sum
}

func main() {
    numbers := []int{1, 2, 3, 4, 5}

    // создаем канал
    c := make(chan int)

    // запускаем горутину для вычисления суммы и передачи результата в канал
    go sum(numbers, c)

    // получаем результат из канала
    result := <-c

    fmt.Println("Sum:", result)
}


В этом примере создается канал, через который горутина sum передает результат вычисления суммы чисел в главную горутину. С помощью оператора <- c главная горутина получает результат из канала и выводит его в консоль.


Это лишь некоторые примеры использования многопоточности в Go. Язык предлагает множество других возможностей и инструментов для работы с горутинами, и вы можете изучить их в документации по Go.