Документация оператора lock
довольно проста:
lock (x)
{
// Your code...
}
, где x - это выражение ссылочного типа .
Поэтому мне нельзя разрешать передавать тип значения в качестве блокировщика для lock
.Однако я заметил, что могу использовать тип значения, который реализует интерфейс.Другими словами, я могу сделать это:
IDisposable locker = default(DisposableStruct);
lock (locker) Console.WriteLine("Thread safe");
struct DisposableStruct : IDisposable
{
public void Dispose() { }
}
Это было удивительно.Я понял, что причина в том, что тип значения в штучной упаковке.Согласно документации :
Бокс - это процесс преобразования типа значения в тип object
или любого типа интерфейса , реализованный этимтип значения.
Мой вопрос: есть ли какие-либо предостережения с использованием типов значений в штучной упаковке в качестве блокировок для оператора lock
.Существует ли какая-либо возможность для оболочки ссылочного типа измениться во время выполнения программы, что приведет к сбою потока-безопасного кода?
Обновление: Вот примерчто беспокоит меняГарантируется ли, что если я выполню код ниже миллиона раз, всегда будет отображаться правильный вывод (1 000 000 000)?
IComparable<int> boxedValueType = 0;
int sharedState = 0;
var tasks = Enumerable.Range(0, 10).Select(_ => Task.Run(() =>
{
for (int i = 0; i < 100_000_000; i++)
lock (boxedValueType)
sharedState++;
})).ToArray();
Task.WaitAll(tasks);
Console.WriteLine(sharedState);