2016-12-23 9 views
0

В пределах Kubernetes Go repo on Github.com,Имеет ли следующий код без блокировки состояние гонки?

Существует блокировка реализации структуры данных HighWaterMark. Этот код опирается на атомные операции для обеспечения безопасного потока, который не содержит данных.

// HighWaterMark is a thread-safe object for tracking the maximum value seen 
// for some quantity. 
type HighWaterMark int64 

// Update returns true if and only if 'current' is the highest value ever seen. 
func (hwm *HighWaterMark) Update(current int64) bool { 
    for { 
     old := atomic.LoadInt64((*int64)(hwm)) 
     if current <= old { 
      return false 
     } 
     if atomic.CompareAndSwapInt64((*int64)(hwm), old, current) { 
      return true 
     } 
    } 
} 

Этот код основан на функциях atomic.LoadInt64 и atomic.CompareAndSwapInt64 в стандартной библиотеке для достижения гонки данных свободного кода ... который я считаю, что это делает, но я верю, что есть еще одна проблема состояния гонки.

Если два конкурирующих потока (goroutines) выполняют такой код, то существует край, где после того, как в первом потоке встречается atomic.LoadInt64, второй поток мог бы поменять место на более высокое значение. Но после первого потока считаетcurrent int64 фактически больше, чем old int64 произойдет обмен. Этот обмен затем будет эффективно уменьшать сохраненное значение из-за наблюдения за устаревшим значением old.

ответ

1

Если другой поток попал в середину, CompareAndSwap завершится неудачно, и цикл начнется.

Придумайте сравнение с обменом, как

if actual == expected { 
    actual = newval 
} 

но сделано атомарно

Так этот код говорит:

old = hwm // but done in a thread safe atomic read way 
if old < current { 
    set hwm to current if hwm == old // atomically compare and then set value 
} 

когда CAS (сравнение с обменом) терпит неудачу, он возвращает ложь, в результате чего цикл, чтобы начать до тех пор, пока либо:

a) "ток" не больше hwm

или

б) Он успешно выполняет нагрузки, а затем без другого сравнение с обменом нити в середине

+0

Aha! Он только что щелкнул меня после прочтения вашего ответа примерно 5 раз. –