2013-02-11 2 views
12

Учитывая следующий класс:Необходим несколько объектов блокировки?

class x 
{ 
    Object lockOne = new Object(); 
    Object lockTwo = new Object(); 

    List<Something> listOne = new List<Something>(); 
    List<Something> listTwo = new List<Something>(); 

    void MethodOne() 
    { 
     lock(lockOne) 
     { 
      // some operation on listOne 
     } 
    } 

    void MethodTwo() 
    { 
     lock(lockTwo) 
     { 
      // some operation on listTwo 
     } 
    } 
} 

Правильно ли использовать два запорных объектов, предполагая, что MethodOne() и MethodTwo() могут быть вызваны из различных потоков одновременно, отметив, что listOne и listTwo не связаны в любом случае. Единственными операциями, связанными с блокировками, являются операции, указанные в комментариях выше.

+1

Это называется замок Расщепление и является хорошим способом уменьшить конкуренцию, если два объекта и методы независимый. – assylias

+0

Его следует называть здравым смыслом, делать это наоборот - очень плохая практика. – Dariusz

+0

Одна вещь, которую вы можете захотеть, это использовать [ReaderWriterLock] (http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx). Если вы только читаете из списка, он позволяет использовать несколько потоков сразу («Список» имеет потокобезопасные чтения), как только вам нужно написать, что вы обновляете блокировку, и только один поток может писать, и все читатели блокируются, после этого несколько считывателей могут начать снова. –

ответ

7

Да, это правильно. Он избегает ненужного блокирования одного списка только потому, что работает другой список.

+2

Правильно? Да. Расточительное? Также да, здесь нет необходимости в отдельных объектах блокировки. – svick

+4

Чтобы уточнить, что сказал svick, он не говорит, чтобы блокировать один объект блокировки, но [не использовать никаких объектов блокировки вообще] (http://stackoverflow.com/a/14814386/80274) и блокировать сам список , –

6

Здесь нет необходимости в отдельных объектах блокировки. Следующий код будет работать так же хорошо, с меньшим количеством кода, меньше накладных расходов и меньше шансов ошибочного использования неправильный замок:

class x 
{ 
    List<Something> listOne = new List<Something>(); 
    List<Something> listTwo = new List<Something>(); 

    void MethodOne() 
    { 
     lock (listOne) 
     { 
      // some operation on listOne 
     } 
    } 

    void MethodTwo() 
    { 
     lock (listTwo) 
     { 
      // some operation on listTwo 
     } 
    } 
} 
+10

Как замечание, лучшая практика (например, это показывает) заключается только в том, чтобы блокировать объекты, которые являются «частными» для класса, - иначе вы не знаете, какой внешний код может попытаться заблокировать его, когда и вызвать взаимоблокировки или условия гонки , –

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