Это подробный вопрос для C #.
Предположим, у меня есть класс с объектом, и этот объект защищен блокировкой:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
return property;
}
set {
property = value;
}
}
Я хочу, чтобы поток опроса мог запрашивать это свойство. Я также хочу, чтобы поток периодически обновлял свойства этого объекта, и иногда пользователь может обновлять это свойство, а пользователь хочет видеть это свойство.
Будет ли следующий код правильно блокировать данные?
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
lock (mLock){
return property;
}
}
set {
lock (mLock){
property = value;
}
}
}
Под «правильно» я имею в виду, если я хочу позвонить
MyProperty.Field1 = 2;
или еще, будет ли поле заблокировано во время обновления? Является ли настройка, которая выполняется оператором equals, в области действия функции get, или сначала завершится функция get (и, следовательно, блокировка), а затем вызывается настройка, а затем - set, минуя таким образом замок?
Редактировать: Поскольку это, очевидно, не сработает, что будет? Нужно ли делать что-то вроде:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
MyObject tmp = null;
lock (mLock){
tmp = property.Clone();
}
return tmp;
}
set {
lock (mLock){
property = value;
}
}
}
, который более или менее просто гарантирует, что у меня есть только доступ к копии, что означает, что если бы у меня было два потока, вызывающих 'get' одновременно, каждый из них начинал бы с одинакового значения Field1 (справа) ?). Есть ли способ сделать блокировку чтения и записи для свойства, которое имеет смысл? Или я должен ограничиться блокировкой секций функций, а не самих данных?
Просто, чтобы этот пример имел смысл: MyObject - это драйвер устройства, который возвращает статус асинхронно. Я посылаю ему команды через последовательный порт, а затем устройство отвечает на эти команды в свое приятное время. Прямо сейчас у меня есть поток, который опрашивает его на предмет его статуса («Вы все еще там? Можете ли вы принимать команды?»), Поток, который ожидает ответов на последовательный порт («Только что получил строку состояния 2, все хорошо» ), а затем поток пользовательского интерфейса, который принимает другие команды («Пользователь хочет, чтобы вы сделали это».) и отправляет ответы от драйвера («Я только что сделал это, теперь обновите интерфейс с этим»). Вот почему я хочу заблокировать сам объект, а не поля объекта; это было бы огромное количество блокировок, a и b, не каждое устройство этого класса имеет одинаковое поведение, только общее поведение, поэтому мне пришлось бы кодировать множество отдельных диалогов, если бы я индивидуализировал блокировки.