Между этими двумя точками может быть состояние гонки. Представьте себе, что произойдет, если вы выполните функцию doSomething()
в двух отдельных потоках, например:
- Первый поток выполняет закрытие
increaseWork()
и завершает его. Прямо сейчас он находится на линии ожидания - Второй поток начинает выполнение и нажимает асин c инструкция выполнения
- Первый поток обращается к инструкции возврата, поскольку ожидание может продолжаться
- В то же время запланировано и выполняется замыкание со второй стороны
На данный момент вы не можете точно сказать, что выполняется первым: sum = sum + 100
из второго потока или return sum
от первого.
Идея состоит в том, что sum
является общим ресурсом, который не синхронизирован, поэтому, теоретически, это может быть условием гонки. Даже если вы позаботились о том, чтобы этого не произошло, Thread Sanitizer обнаруживает возможное состояние гонки, поскольку он не знает, запускаете ли вы один поток или выполняете функцию doSomething()
из 100 различных потоков одновременно.
ОБНОВЛЕНИЕ:
Поскольку я пропустил тот факт, что переменная sum
является локальной, приведенное выше объяснение не отвечает на текущий вопрос. Описанный сценарий никогда не будет реализован в данном фрагменте кода.
Но, хотя sum
является локальной переменной, из-за того, что она используется и сохраняется внутри замыкания, она будет выделена в куче, а не в стеке. Это связано с тем, что компилятор Swift не может определить, будет ли закрытие завершено до выполнения функции doSomething()
или нет.
Почему? Потому что замыкание передается конструктору, который ведет себя как параметр @escaping
. Это означает, что нет гарантии того, что замыкание будет выполнено, поэтому все переменные, сохраняемые замыканием, должны быть размещены в куче для безопасности. Не зная, когда будет выполнено замыкание, Thread Sanitizer не может определить, будет ли действительно выполняться оператор return sum
после того, как замыкание завершится.
Так что даже здесь мы можем быть уверены, что ни одно из состязаний не может возникнуть, Thread Sanitizer вызывает тревогу, так как не может определить, что это не может произойти.