Понимание атомарного добавления и мьютекса - PullRequest
0 голосов
/ 17 ноября 2018

Я тестирую параллелизм приращения itemID в функции обработчика ниже, и иногда приращение пропускает значение (пример: 4, 6, 7, ... пропущенный идентификатор 5).

func proxyHandler() http.Handler {
    var itemID int32
    return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        proxy := httputil.NewSingleHostReverseProxy(url)
        proxy.ModifyResponse = func(res *http.Response) error {
            item := Item{
                ID: int(atomic.AddInt32(&itemID, 1)),
            }
            items.Add(item)
            return nil
        }
        proxy.ServeHTTP(rw, req)
    })
}

Я решил это с помощью Mutex:

func proxyHandler() http.Handler {
    itemID := 0
    mux := sync.Mutex{}
    return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        proxy := httputil.NewSingleHostReverseProxy(url)
        proxy.ModifyResponse = func(res *http.Response) error {
            mux.Lock()
            itemID++
            item := Item{
                ID: itemID,
            }
            items.Add(item)
            mux.Unlock()
            return nil
        }
        proxy.ServeHTTP(rw, req)
    })
}

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

1 Ответ

0 голосов
/ 17 ноября 2018

atomic.AddInt32() отлично подходит для одновременного использования несколькими программами. Вот почему он находится в пакете atomic. Ваша проблема с Items.Add(), которую вы указали в комментариях как отсутствие защиты от блокировки.

Это грубое определение для сейфа Items.Add()

type Items struct {
    items []Item
    lock  sync.Mutex
}

func (i *Items) Add(item Item) {
    i.lock.Lock()
    defer i.lock.Unlock()
    i.items = append(i.items, item)
}

С приведенным выше определением Items теперь вы можете использовать свой исходный код с atomic.AddInt32(). Однако я хотел бы отметить, что вы не должны читать Items, пока к нему добавляются другие темы. Даже чтения должны быть синхронизированы.

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