Понимание изменения количества ссылок на объект при работе с очередями

Как понять что выведет во всех печатать, и в каком порядке (см код ниже)? С порядком я разобрался и с подсчетом ссылок на объект вроде как тоже, можете дать какой-то фидбэк по тому правильно я все понял или нет?

// вызываем на главном потоке   
let serialQueue = DispatchQueue.main
let object = NSObject()   // (1) +1 = 1
serialQueue.async {  // (2) клоужер захватил объект +1 = 2
    print("A", CFGetRetainCount(object)) // (5) функция захватила объект +1 = 3 -> print A 3
                                        //  (6) функция отпускает объект -1 = 2
    serialQueue.async { // (7) клоужер захватил объект +1 = 3
                       //  (10) клоужер который снаружи убивается поэтому -1 = 2
        print("B", CFGetRetainCount(object)) //  (11) функция захватила объект +1 = 3 -> print B 3
    }
    print("C", CFGetRetainCount(object)) // (8) функция захватила объект +1 = 4 -> print C 4
                                            // (9) функция отпускает объект -1 = 3

    }
    print("D", CFGetRetainCount(object))  // (3) функция захватила объект +1 = 3   -> print D 3
                                            // (4) функция отпускает объект -1 = 2
}

Но вот в этом случае я не могу понять каким образом увеличиваются ссылки на объект, но очень хочется понять, может кто направить в нужное русло? В логе выводится D 5 | A 5 | C 4 | B 3, не могу понять почему в D и A стало по 5 указателей вместо 3

// вызываем на главном потоке   
let serialQueue = DispatchQueue.init(label: "myQueue")
let object = NSObject()   
serialQueue.async {  
    print("A", CFGetRetainCount(object))                                             
    serialQueue.async {                            
        print("B", CFGetRetainCount(object)) 
    }
    print("C", CFGetRetainCount(object))                                           
} 
print("D", CFGetRetainCount(object)) 
1
задан Kromster 31 May 2018 в 04:14
поделиться

1 ответ

Мой вывод 1го примера отличается:

D 3 //Принадлежит переменной и захвачен кложуром
A 2 //В этот момент переменной object не существует, она захвачена только кложуром.
C 3 //Помимо текущего кложура захвачено еще новым кложуром.
B 2 //Тут первый кложур завершен, объект захвачен только текущим кложуром.

Теперь рассмотрим 2й пример. Тут уже видна гонка, каждый раз в лог выводит разный результат и порядок. В первом случае мы вызываем все из главного потока, поэтому только один кложур исполняется в один момент времени. Во 2-м случае у нас отдельная очередь и она сражается с главным потоком - main. D: может вызваться после вызова распечатать D но до выхода из печати, а может вызываться и после как в 1м примере. И это уже влияет на то что выведется в лог.

А вот уже 2й кложур гарантированно вызовется только после завершения 1го кложура - очередь то последовательная.

0
ответ дан ViR 6 June 2018 в 08:59
поделиться
  • 1
    спасибо за ответ, разобрался – user3555920 31 May 2018 в 07:04
  • 2
    А подскажите пожалуйста почему " В этот момент переменный объект не существует " ? – user3555920 31 May 2018 в 07:12
  • 3
    Сам объект существует, а вот перемен объект уже нет - память освобождена (счетчик ссылок уменьшился на 1) т.к. после выполнения кода вышли за пределы видимости переменной – ViR 31 May 2018 в 07:45
  • 4
    Если мой ответ решил проблему, можно его отметить как решить вопроса;) – ViR 31 May 2018 в 07:47

Другие вопросы по тегам:

Похожие вопросы: