Хорошо, я просто не могу правильно разобраться в многопоточных сценариях. Извините за повторный аналогичный вопрос, я просто вижу много разных "фактов" в Интернете.
public static class MyClass {
private static List<string> _myList = new List<string>;
private static bool _record;
public static void StartRecording()
{
_myList.Clear();
_record = true;
}
public static IEnumerable<string> StopRecording()
{
_record = false;
// Return a Read-Only copy of the list data
var result = new List<string>(_myList).AsReadOnly();
_myList.Clear();
return result;
}
public static void DoSomething()
{
if(_record) _myList.Add("Test");
// More, but unrelated actions
}
}
Идея заключается в том, что если запись активирована, вызовы DoSomething() записываются во внутренний список и возвращаются при вызове StopRecording().
Моя спецификация такова:
- StartRecording не считается потокобезопасным. Пользователь должен вызывать это, пока другой Thread не вызывает DoSomething(). Но если это так или иначе, это будет здорово.
- StopRecording также не является официально потокобезопасной. Опять же, было бы здорово, если бы это было так, но это не требование.
- DoSomething должен быть потокобезопасным
Обычно выглядит так:
public static void DoSomething()
{
object _lock = new object();
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
Альтернативно, объявляя статическую переменную:
private static object _lock;
public static void DoSomething()
{
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
Однако этот ответ говорит, что это не мешает доступу другого кода.
Так что я задаюсь вопросом
- Как правильно заблокировать список?
- Должен ли я создать объект блокировки в моей функции или как статическую переменную класса?
- Могу ли я обернуть функциональность Start и StopRecording в блоке блокировки?
- StopRecording() делает две вещи: установите логическую переменную в false (чтобы DoSomething() не добавлял больше материала), а затем копирование списка, чтобы вернуть копию данных вызывающему абоненту). Я предполагаю, что _record = false; является атомным и будет действовать немедленно? Поэтому обычно мне не нужно беспокоиться о Multi-Threading вообще, если какой-то другой Thread не вызывает снова StartRecording()?
В конце дня я ищу способ выразить "Хорошо, этот список принадлежит мне сейчас, все остальные потоки должны ждать, пока я не сработаю".