2009-10-23 3 views
10

В моем многопоточном приложении я использую некоторые переменные, которые могут быть изменены многими экземплярами за одно и то же время. Это странно, но он отлично справился без проблем ... но, конечно, мне нужно сделать его потокобезопасным. Я только начинаю с замков, поэтому я буду жаловаться на ваши советы:Замок в свойствах, хороший подход?

Когда клиент подключается, создается класс Client, где каждый клиент имеет свою переменную «A».

Иногда клиент не вызывает метод так:

Client selectedClient SelectOtherClientClassByID(sentID); 

selectedClient.A=5; 

Нет проблем до сих пор с этим, даже когда 5 классов делали в то же время (Threadpool), но я думал, что о добавлении замки A свойств ?

Как:

A { 
    get { return mA; } 
    set { 
     // use lock here for settting A to some value 
    }  
} 

Будет ли в порядке?

ответ

16

Вам необходимо использовать блокировки в BOTH get and set. Этот замок должен быть одним и тем же объектом. Например:

private object mylock = new object(); 

public int A { 

    get { 
    int result; 
    lock(mylock) { 
    result = mA; 
    } 
    return result; 
    } 

    set { 
    lock(mylock) { 
     mA = value; 
    } 
    } 
} 
+1

Спасибо ... btw для чтения потому что он может измениться во время чтения другим классом? – Petr

+1

Не стоит запираться на этом, так как он доступен извне. –

+0

Это может измениться во время настройки. Замок действует как барьер, предотвращая любые другие действия, пока владелец замка не освободит замок. –

2

Это очень редко, когда все, что вам нужно, это просто установить одно свойство. Чаще всего selectedClient.A = 5 будет частью гораздо большей логической операции, которая включает в себя несколько присвоений/оценок/и т. Д. Во время этой операции вы предпочтете, чтобы selectedClient был в состоянии согласованности и не вводил взаимоблокировки/условия гонки. Таким образом, это будет гораздо лучше, чтобы выставить SyncRoot свойства в вашем Client класса и замок на том, что из вызывающего кода:

Client selectedClient = GetClient(...); 

lock(selectedClient.SyncRoot) 
{ 
    selectedClient.A = 5; 
    selectedClient.B = selectedClient.A * 54; 
} 
+0

У меня нет других переменных, чем один список и те int. В основном, я ничего не знаю о SyncRoot :) – Petr

+0

SyncRoot не рекомендуется: см. Http://blogs.msdn.com/brada/archive/2003/09/28/50391.aspx –

+0

@_NT: Цитата из сообщения в блоге: «Будьте уверены, что мы не допустим такой же ошибки, как мы собираем общие версии этих коллекций.«И вот мы, 6 лет спустя, со списком .SyncRoot без каких-либо обескураживающих заметок в MSDN: http://msdn.microsoft.com/en-us/library/bb356596.aspx –

6

Блокировка доступа к свойствам внутри аксессоров может привести к фиктивным результатам. Для примера, рассмотрим следующий код:

class C { 
    private object mylock = new object(); 

    public int A { 

     get { 
     int result; 
     lock(mylock) { 
     result = mA; 
     } 
     return result; 
     } 

     set { 
     lock(mylock) { 
      mA = value; 
     } 
     } 
    } 
} 
C obj = new C; 
C.A++; 

(да, я скопировал его из первого ответа) Существует состояние гонки здесь! Операция «C.A ++» фактически требует двух отдельных доступов к A, один для получения значения, а другой - для установки обновленного значения. Ничто не гарантирует, что эти два доступа будут выполняться вместе, без переключения контекста между ними. Классический сценарий состояния гонки!

Итак, остерегайтесь! Не стоит помещать блокировки внутри аксессуаров, блокировки должны быть явно получены, как и предыдущий ответ (хотя он не обязательно должен быть с SyncRoots, любой объект будет делать)

+0

Кроме того, вы имеете в виду, что вручную добавить объект блокировки ко всем вызовам в коде? Я думаю, что до сих пор в моем коде есть как минимум 20 показаний и 15 писем. – Petr

+0

Для этого вы расширяете свой замок, чтобы покрыть всю критическую область. t do A ++ –

+0

NT: Я не понимаю вас хорошо, возможно. У меня есть около 15 методов с различными операциями с этой переменной на разных экземплярах. Я не уверен, как вы хотели развернуть loc к. Так что замок свойств не очень хорошо, если я правильно прочитал все выше – Petr

Смежные вопросы