Голанг: для чего используется атомарное чтение? - PullRequest
1 голос
/ 25 апреля 2019

Здесь у нас есть ход, предоставленный Go by Example для объяснения атомарного пакета.

https://gobyexample.com/atomic-counters

package main

import "fmt"
import "time"
import "sync/atomic"

func main() {

    var ops uint64

    for i := 0; i < 50; i++ {
        go func() {
            for {
                atomic.AddUint64(&ops, 1)

                time.Sleep(time.Millisecond)
            }
        }()
    }

    time.Sleep(time.Second)

    opsFinal := atomic.LoadUint64(&ops) // Can I replace it?
    fmt.Println("ops:", opsFinal)
}

Для atomic.AddUnit64 это просто понять.

Вопрос1

Что касается операции read, почему необходимо использовать atomic.LoadUnit, а не читать этот счетчик напрямую?

Вопрос2

МожетЯ заменяю последние две строки на следующие строки?

До

    opsFinal := atomic.LoadUint64(&ops) // Can I replace it?
    fmt.Println("ops:", opsFinal)

После

    opsFinal := ops
    fmt.Println("ops:", opsFinal)

Вопрос3

Обеспокоены ли мы этим сценарием?

  1. CPU загружает данные из памяти
  2. CPU манипулирует данными
  3. Записывает данные обратно в память.Несмотря на то, что этот шаг быстрый, но он все же требует времени.

Когда процессор выполняет шаг 3, другая процедура может считывать неполные и грязные данные из памяти.Так что использование atomic.LoadUint64 могло бы избежать проблем такого рода?

Ссылка

Доступны ли операции чтения и записи для uint8 в golang atomic?

1 Ответ

8 голосов
/ 25 апреля 2019

Необходимо использовать atomic.LoadUint64, потому что нет гарантии, что оператор := выполняет атомарное чтение.

Для примера рассмотрим теоретический случай, когда atomic.AddUint64 реализован следующим образом:

  1. Взять замок.
  2. Читать младшие 32 бита.
  3. Читать старшие 32 бита.
  4. Добавьте число к младшим 32 битам.
  5. Добавить выполнение первой операции в старшие 32 бита.
  6. Запишите младшие 32 бита.
  7. Запишите старшие 32 бита.
  8. Снять блокировку.

Если вы не используете atomic.LoadUint64, вы можете прочитать промежуточный результат между шагами 6 и 7.

На некоторых платформах (например, более старые процессоры ARM без встроенной поддержки 64-битных целочисленных операций) это вполне может быть реализовано способом, описанным выше.

То же самое относится и к целым числам / указателям других размеров. Точное поведение будет зависеть от реализации пакета atomic и архитектуры ЦП / памяти, на которой работает программа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...