Поиск

Безопасность и синхронизация потоков

При программировании для однопоточного окружения методы зачастую пишутся так, что на некоторых этапах исполнения кода объекты временно находятся в недействительном состоянии. Очевидно, что если в любой момент к объекту обращается только один поток, у вас есть гарантия, что каждый метод завершится до того, как будет вызван следующий метод. Это значит, что для своих клиентов объект всегда пребывает в действительном состоянии. Однако когда несколько потоков работают одновременно, вы легко можете получить ситуации, в которых процессор переключается на другой поток, в то время как ваш объект находится в недействительном состоянии. Если затем этот поток также попытается использовать этот же объект, результат будет совершенно непредсказуем. Поэтому термин "безопасность потоков" означает постоянное поддержание членов объекта в действительном состоянии при их одновременном использовании несколькими потоками.

Как избежать подобных непредсказуемых состояний? На самом деле, как это обычно бывает в программировании, существует несколько способов решения этой хорошо известной проблемы. В этом разделе я расскажу о стандартном средстве — синхронизации. Синхронизация позволяет задавать критические секции (critical sections) кода, в которые в каждый отдельный момент может входить только один поток, гарантируя, что любые временные недействительные состояния вашего объекта будут невидимы его клиентам. Мы рассмотрим несколько средств определения критических секций, включая классы .NET Monitor и Mutex, а также оператор С# lock.