Как работать с конкурентностью в Golang?

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

от theron , в категории: Общие вопросы , 2 года назад

Как работать с конкурентностью в Golang?

Facebook Vk Ok Twitter LinkedIn Telegram Whatsapp Pocket

2 ответа

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

от caitlyn_wehner , 2 года назад

@theron 

Golang предоставляет несколько механизмов для работы с конкурентностью. Ниже приведены некоторые из них:

  1. Горутины (goroutines): это легковесные потоки, которые работают параллельно внутри одного процесса. Для создания горутины необходимо использовать ключевое слово go.Например:func main() { go func() { // some code here }() }
  2. Каналы (channels): это механизм передачи данных между горутинами. Они гарантируют безопасность при работе с разделяемыми данными, так как обеспечивают синхронизацию доступа к данным.Например:func main() { c := make(chan int) go func() { c <- 42 }() fmt.Println(<-c) }
  3. Mutex: это блокировки, которые используются для защиты общих ресурсов. Они гарантируют, что только одна горутина может иметь доступ к разделяемым данным в любой момент времени.Например:var mutex = &sync.Mutex{} func main() { counter := 0 for i := 0; i < 1000; i++ { go func() { mutex.Lock() counter++ mutex.Unlock() }() } time.Sleep(time.Second) fmt.Println("Counter:", counter) }


Эти механизмы могут быть использованы вместе для создания безопасного и эффективного параллельного кода в Golang. Однако, при работе с конкурентностью необходимо учитывать возможные проблемы, такие как гонки данных (data races) и взаимная блокировка (deadlock), и применять соответствующие методы для их избежания.

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

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

@theron 

Также в Golang существуют такие понятия, как WaitGroup и Select.


WaitGroup - это средство синхронизации, которое позволяет дождаться завершения выполнения определенной группы горутин, прежде чем продолжить выполнение основной горутины. Пример использования WaitGroup:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var wg sync.WaitGroup

func main() {
    wg.Add(2) // Указываем количество горутин, которые нужно дождаться
    go worker()
    go worker()
    wg.Wait() // Ожидаем завершения работы всех горутин
    fmt.Println("All workers have finished")
}

func worker() {
    defer wg.Done() // Уменьшаем счетчик завершенных горутин
    // some code here
}


Select - это механизм выбора между несколькими операциями ввода/вывода. Он позволяет обрабатывать события, которые станут доступны в каналах, независимо от порядка их поступления. Пример использования Select:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func main() {
    c1 := make(chan int)
    c2 := make(chan int)

    go func() {
        time.Sleep(time.Second)
        c1 <- 10
    }()

    go func() {
        time.Sleep(time.Second * 2)
        c2 <- 20
    }()

    for i := 0; i < 2; i++ {
        select {
        case n := <-c1:
            fmt.Println("Received from c1:", n)
        case n := <-c2:
            fmt.Println("Received from c2:", n)
        }
    }
}


Эти механизмы помогут вам эффективно работать с конкурентностью в Golang.