Код переписан, чтобы не было путаницы, поэтому я надеюсь, что это имеет смысл (и что я не устранил проблему, переписав код). Проблема в том, что иногда defer Mutex.Unlock()
никогда не происходит, делая списки заблокированными навсегда, как описано ниже
У меня есть список OuterStruct
, где каждый элемент содержит список InnerInt
. Оба этих списка могут изменяться одновременно в зависимости от происходящего. В нашем случае, если соединение websocket выходит из строя или появляется.
У меня есть функция, которая возвращает некоторые данные из каждого OuterStruct
, включая значения int для всех InnerInt
объектов для каждого OuterStruct
. Итак, поскольку оба этих списка можно изменять одновременно, я использую Mutex для обоих из них. Итак, сначала я блокирую «внешний» список и выполняю defer outerStructList.Mutex.Unlock()
. Затем я перебираю внешний список и для каждого элемента запускаю (outer *OuterStruct) getInnerInts()
. Эта функция сделает Mutex.Lock()
во внутреннем списке. Итерируйте этот список, получите все фактические значения int и верните массив этих int. Внешняя функция установит этот массив в одно из полей возвращаемого объекта плюс другое поле, а затем перейдет к следующему объекту.
Иногда случается, что Unlock () во внутреннем списке никогда бывает. Хотя я использую defer outer.InnerInts.Mutex.Unlock()
. Единственное, что происходит после этого, - это то, что я повторяю элементы и добавляю значение int в массив целых чисел, затем массив возвращается, и в этот момент, как я предполагаю, должно произойти Unlock
.
Я знаю из этого я, вероятно, мог бы немного улучшить этот код, но есть ли у кого-нибудь идеи, почему внутренний мьютекс иногда никогда не разблокируется? Что могло бы случиться между Lock()
и функциональностью функции (итерация массива), чтобы функция никогда не возвращалась и, следовательно, Mutex никогда не разблокировался?
func getAllOuterStructs() []int {
outerStructsList.Mutex.Lock()
defer outerStructsList.Mutex.Unlock()
var returnOuterStructsToSend []OuterStructToSend
for _, rangedOuterStruct := range outerStructsList {
outerStructToSend := OuterStructToSend{}
outerStructToSend.OtherValue := rangedOuterStruct.OtherValue
outerStructToSend.IntList := rangedOuterStruct.getInnerInts()
returnOuterStructsToSend = append(returnOuterStructsToSend, outerStructToSend)
}
return returnOuterStructsToSend
}
func (outer *OuterStruct) getInnerInts() []int {
outer.InnerInts.Mutex.Lock()
defer outer.InnerInts.Mutex.Unlock()
outerInts := outer.InnerInts
var returnInts []int
for _, rangedInt := range outerInts {
returnInts = append(returnInts, rangedInt.IntVal)
}
return returnInts
}