Нужен ли мьютекс при замене значения строки в разных программах? - PullRequest
0 голосов
/ 22 мая 2019

Нужен ли мьютекс в этом случае?Я обновляю токен с помощью goroutine, токен используется в другом goroutine.Другими словами, будет ли мой токен пустым в какой-то момент, так что ответ будет 401?

Если да, является ли он частью структуры c *threatq или это простая переменная, я имею в виду"автономный" внутри моего кода.

// IndicatorChannelIterator returns indicators from ThreatQ into a channel.
func (c *threatq) IndicatorChannelIterator() (<-chan *models.Indicator, error) {
    // Authenticate
    token, err := c.authenticate(c.clientID, c.email, c.password)
    if err != nil {
        return nil, fmt.Errorf("Error while authenticating to TQ : %s", err)
    }

    // Periodically refresh the token
    ticker := time.NewTicker(30 * time.Minute)
    go func() {
        for range ticker.C {
            token, err = c.authenticate(c.clientID, c.email, c.password)
            if err != nil {
                logrus.Errorf("Error while authenticating to TQ : %s", err)
            }
        }
    }()

    // Prepare the query
    query := &Query{}

    // Get the first page
    firstTQResponse, err := c.advancedSearch(query, token, 0)
    if err != nil {
        return nil, fmt.Errorf("Error while getting the first page from TQ : %s", err)
    }

    // Create the channel
    indicators := make(chan *models.Indicator)

    // Request the others
    go func() {
        req := 1
        total := firstTQResponse.Total
        for offset := 0; offset < total; offset += c.perPage {    
            // Search the indicators
            tqResponse, err := c.advancedSearch(query, token, offset)
            if err != nil {
                logrus.Errorf("Error while getting the indicators from TQ : %s", err)
                continue
            }

...

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Правило простое: если к переменной обращаются из нескольких подпрограмм, и хотя бы одна из них является записью, необходима явная синхронизация.

Это верно в вашем случае: одна из ваших подпрограмм записываетtoken переменная (а также переменная err!), А другая читает ее, поэтому вы должны синхронизировать доступ.

Поскольку token не является полем структуры threatq, добавление мьютексакоторый защищает это не будет мудрым.Всегда устанавливайте мьютекс близко к данным, которые он должен защищать.

Некоторые примечания: как упоминалось ранее, вы также пишете и читаете локальную переменную err из нескольких процедур.Вы не должны этого делать, вместо этого создайте другую локальную переменную для хранения ошибки из других подпрограмм (если вы не хотите «перевести» ошибку между подпрограммами, но здесь это не так).

См. Связанные вопросы:

Неизменяемость строки и параллелизма

Должны ли мы синхронизировать присвоение переменной в процедуре?

одновременное чтение golang structи запись без блокировки также работает нормально?

Чтение значений из другого потока

Почему этот код вызывает гонку данных?

0 голосов
/ 22 мая 2019

Да, вы также можете попробовать запустить этот тест с включенным флагом -race.Детектор расы Go, вероятно, скажет вам, что токен является общей переменной для нескольких программ.Таким образом, он должен быть защищен с помощью Mutex или RWMutex.

. В вашем случае я считаю, что RWMutex более уместно, поскольку существует одна процедура, которая изменяет (т.е. записывает) состояние * 1007.* каждые 30 минут и другая процедура, которая считывает его значение.

Если вы не защитите общую переменную с помощью блокировки, вторая программа может прочитать старое значение token, срок действия которого может истечь.

...