Это подробный вопрос для С#.
Предположим, что у меня есть класс с объектом, и этот объект защищен блокировкой:
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, все хорошее" )), а затем поток пользовательского интерфейса, который принимает другие команды ( "Пользователь хочет, чтобы вы делали это".) и отправляет ответы от драйвера ( "Я только что сделал, теперь обновляю интерфейс с этим" ). Поэтому я хочу блокировать сам объект, а не поля объекта; это было бы огромное количество блокировок, а и b, не все устройства этого класса имеют одинаковое поведение, просто общее поведение, поэтому мне пришлось бы кодировать множество отдельных диалогов, если бы я индивидуализировал блокировки.