Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

Iskander (Alex) Sharipov

December 08, 2018
Tweet

More Decks by Iskander (Alex) Sharipov

Other Decks in Programming

Transcript

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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

  5. Каналы, оператор for
    ch := make(chan DataType, capacity) // создать
    close(ch) // закрыть
    ch <- struct{}{} // запись
    data <- ch // чтение
    for data := range ch { ... } // чтение через цикл
    1.
    2.
    3.
    4.
    5

    View Slide

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

    View Slide

  7. Ошибки в использовании select
    select {
    case <- time.NewTicker(time.Second * 2).C:
    ...
    case <- time.NewTicker(time.Second * 1).C:
    ...
    }
    7

    View Slide

  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

    View Slide

  9. Ошибки в использовании select
    for {
    select {
    case <- ch:
    ...
    default:
    // без блокирующих операций 100% загрузка CPU
    }
    }
    9

    View Slide

  10. Если канал закрыт
    close(ch)
    select {
    case v, success := <- ch: // success == false
    }
    ch <- data // panic
    1.
    2.
    3.
    10

    View Slide

  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

    View Slide

  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

    View Slide

  13. sync.WaitGroup
    Когда нужно дождаться выполнения всех горутин
    var wg sync.WaitGroup
    for _, task := range tasks {
    wg.Add(1)
    go func() { task.Do(); wg.Done() }
    }
    wg.Wait()
    13

    View Slide

  14. sync.Once
    Выполнение кода один раз, ленивая загрузка
    var once sync.Once
    for i := 0; i < 10; i++ {
    go func() { // иницализация будет выполнена один раз
    once.Do(lazyInitialize)
    }()
    }
    14

    View Slide

  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

    View Slide

  16. sync.Map
    16

    View Slide

  17. sync.Pool
    17

    View Slide

  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

    View Slide

  19. atomic
    19

    View Slide

  20. atomic
    atomic.Add* // изменение значения
    atomic.CompareAndSwap* // поменять значения местами если отличаются
    atomic.Swap* // поменять значения местами
    atomic.Load* // прочитать значение
    atomic.Store* // записать значение
    atomic.Value // позволяет читать/писать занчение типа interface{}
    1.
    2.
    3.
    4.
    5.
    6.
    20

    View Slide

  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

    View Slide

  22. Спасибо
    Алексей Павлюков [email protected], на GitHub
    22

    View Slide