Объекты синхронизации в Go

Объекты синхронизации в Go

5b8d20aa7d63c5d391b1c881e1764460?s=128

Iskander (Alex) Sharipov

December 08, 2018
Tweet

Transcript

  1. Объекты синхронизации в Go Алексей Павлюков © Renée French 1

  2. Базовые объекты синхронизации Каналы, операторы select, for sync.Mutex, sync.RWMutex, sync.WaitGroup

    sync.Cond, sync.Once, sync.Map, sync.Pool atomic.Add*, atomic.CompareAndSwap*, atomic.Swap* atomic.Load*, atomic.Store*, atomic.Value 1. 2. 3. 4. 5. 2
  3. Потоки данных 3

  4. Потоки данных 4

  5. Каналы, оператор for ch := make(chan DataType, capacity) // создать

    close(ch) // закрыть ch <- struct{}{} // запись data <- ch // чтение for data := range ch { ... } // чтение через цикл 1. 2. 3. 4. 5
  6. Оператор select select { case ch <- 4: // была

    запись в канал case v := <-ch: // произошло чтение из канала default: // ничего из вышеперечисленного } 6
  7. Ошибки в использовании select select { case <- time.NewTicker(time.Second *

    2).C: ... case <- time.NewTicker(time.Second * 1).C: ... } 7
  8. Как исправить t1 := time.NewTicker(time.Second * 2) t2 := time.NewTicker(time.Second

    * 1) ... select { case <- t1.C: ... case <- t2.C: ... } t1.Stop(); t2.Stop() 8
  9. Ошибки в использовании select for { select { case <-

    ch: ... default: // без блокирующих операций 100% загрузка CPU } } 9
  10. Если канал закрыт close(ch) select { case v, success :=

    <- ch: // success == false } ch <- data // panic 1. 2. 3. 10
  11. Массив каналов chans := []chan int{make(chan int), make(chan int)} cases

    := make([]reflect.SelectCase, len(chans)) for i, ch := range chans { cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)} } chosen, value, ok := reflect.Select(cases) // ok == true если канал не закрыт 11
  12. sync.Mutex, sync.RWMutex var mu sync.Mutex // создать mutex mu.Lock() //

    заблокировать доступ к ресурсу mu.Unlock() // разблокировать доступ к ресурсу var mu sync.RWMutex // Как обычный mutex плюс mu.RLock() // блокировать ресурс на чтение mu.RUnlock() // разблокировать ресурс на чтение 1. 2. 12
  13. sync.WaitGroup Когда нужно дождаться выполнения всех горутин var wg sync.WaitGroup

    for _, task := range tasks { wg.Add(1) go func() { task.Do(); wg.Done() } } wg.Wait() 13
  14. sync.Once Выполнение кода один раз, ленивая загрузка var once sync.Once

    for i := 0; i < 10; i++ { go func() { // иницализация будет выполнена один раз once.Do(lazyInitialize) }() } 14
  15. sync.Cond c := sync.NewCond(&sync.Mutex{}) c.L.Lock() // вызов в горутинах, должен

    быть раньше чем в исто c.Wait() // ждем изменения, работаем со значением или c.Wait() c.L.Unlock() // --- c.L.Lock() // вызов источнике изменений c.Broadcast() // сигнал об изменении, c.Signal() - для одной г c.L.Unlock() 15
  16. sync.Map 16

  17. sync.Pool 17

  18. sync.Pool Многократное повторное использование объектов bufPool := sync.Pool{ New: func()

    interface{} { return new(bytes.Buffer) } } // использование b := bufPool.Get().(*bytes.Buffer) b.Reset() // нужно сбросить состояние перед использованием bufPool.Put(b) // вернуть в pool 18
  19. atomic 19

  20. atomic atomic.Add* // изменение значения atomic.CompareAndSwap* // поменять значения местами

    если отличаются atomic.Swap* // поменять значения местами atomic.Load* // прочитать значение atomic.Store* // записать значение atomic.Value // позволяет читать/писать занчение типа interface{} 1. 2. 3. 4. 5. 6. 20
  21. Ссылки Effective Go Go by Example Разбираемся с новым sync.Map

    в Go 1.9 Concurrency Patterns In Go GopherCon 2017: Kavya Joshi - Understanding Channels 1. 2. 3. 4. 5. 21
  22. Спасибо Алексей Павлюков i@aleksei.co, на GitHub 22