Помощниками блокировки я имею в виду одноразовые объекты, с помощью которых можно реализовать блокировку с помощью операторов using
.Например, рассмотрим типичное использование класса SyncLock
из MiscUtil Джона Скита :
public class Example
{
private readonly SyncLock _padlock;
public Example()
{
_padlock = new SyncLock();
}
public void ConcurrentMethod()
{
using (_padlock.Lock())
{
// Now own the padlock - do concurrent stuff
}
}
}
Теперь рассмотрим следующее использование:
var example = new Example();
new Thread(example.ConcurrentMethod).Start();
Myвопрос заключается в следующем: поскольку example
создается в одном потоке, а ConcurrentMethod
вызывается в другом, поток ConcurrentMethod
не может не обращать внимания на присваивание _padock
в конструкторе (из-за кэширования / чтения потока-записать переупорядочение) и, таким образом, выбросить NullReferenceException
(на _padLock
)?
Я знаю, что блокировка с помощью Monitor
/ lock
имеет преимущество в виде барьеров памяти, но при использовании помощников блокировкиЯ не понимаю, почему такие барьеры гарантированы.В этом случае, насколько я понимаю, конструктор должен быть изменен:
public Example()
{
_padlock = new SyncLock();
Thread.MemoryBarrier();
}
Источник: Понимание влияния методов низкого уровня блокировки в многопоточных приложениях
EDIT Ганс Пассант предполагает, что создание потока подразумевает барьер памяти.А как насчет:
var example = new Example();
ThreadPool.QueueUserWorkItem(s => example.ConcurrentMethod());
Теперь поток не обязательно создан ...