2013-09-24 2 views
2

Мой вопрос может звучать, как и многие другие здесь, но у него есть вкус, которого я не нашел.Раздел кода блокировки в C#

Я пытаюсь понять следующую логику

родового объекта

public class GenericClass 
{ 
    public static void DoSomething(Object lockObj) 
    { 
     lock(lockObj) 
     { 
      // do something here 
     } 
    } 
} 

Класс

internal class A 
{ 
    private static _aLock = new Object(); 

    public void Do_A_Thing() 
    { 
     GenericClass.DoSomething(_aLock); 
    } 
} 

Класс B

internal class B 
{ 
    private static _bLock = new Object(); 

    public void Do_B_Thing() 
    { 
     GenericClass.DoSomething(_bLock); 
    } 
} 

Я просто надеюсь, чтобы подтвердить, еслимое объяснение верное:

Если несколько потоков класса «A» будут пытаться одновременно получить код в методе «genericClass» «DoSomething», этот метод будет заблокирован для всех, кроме одного экземпляра класса «A». Но один экземпляр класса «B» сможет продолжить выполнение в любое время. Если класс «B» также будет иметь несколько экземпляров, они не будут вмешиваться в блокировки класса «A».

Правильно ли это на основании того, что вы видите выше?

+0

Да ... хотя конструкция кажется немного пугающей – Yaur

+0

У вас на самом деле есть ';' в конце 'lock (lockObj);'? Тебе не следует. Это похоже на наличие if (someCondition); {// do stuff} ': вы только применяете' lock' или 'if' к пустой инструкции, обозначенной символом'; ', а не кодовому блоку, указанному' {} '. –

+0

Как правило, вы хотите, чтобы ваши объекты блокировки были закрытыми, так что вы знаете, что никто не может блокировать их.Передача их требует большого доверия (и знаний) вызывающего. –

ответ

3

Да, ваше описание звучит правильно. Возможно, немного необычно передать объект блокировки в, но он будет работать нормально. Единственное изменение, которое я хотел бы предложить, - сделать поля staticreadonly, чтобы вы не могли случайно изменить значение на другую ссылку object.

2

Да, это правильно. Замки в A и замки в B полностью не знают друг о друге. Код будет заблокирован только тогда, когда есть другой поток, блокирующий его с тем же объектом, что и идентификатор.

2

Ваш вывод верный, но не рекомендуется проходить закрытый объект. Я предлагаю поставить lock внутри классов A и B соответственно.

Предлагаю написать:

internal class A 
{ 
    private static readonly _aLock = new Object(); 

    public void Do_A_Thing() 
    { 
     lock (_aLock) 
     { 
      GenericClass.DoSomething(); 
     } 
    } 
} 

У вас есть конкретные причины, чтобы поставить замок в другой класс? Может быть, вы можете решить свою проблему по-другому?

Также имейте в виду, что в некоторых условиях, возможно, это не ваш случай, вы можете иметь тупик, если класс A и B называют друг друга (A-> B-> A).

+0

То, что вы предложили, является типичной ситуацией, которую я использовал сотни раз. Сейчас проблема заключается в том, что я хочу, чтобы общий класс был ... общим. Он должен хранить и извлекать некоторые кеши, требуемые некоторыми объектами. Но у каждого объекта есть собственный кеш. И я хочу не более одного экземпляра каждого типа для извлечения или хранения данных. Одним из решений было бы наследование базового объекта с возможностью кэширования. Но сейчас это невозможно. Похоже, мое мышление подтверждено. –

+0

Является ли это 'GenericClass ', и будет ли объект блокировки зависеть от 'T'? Потому что тогда вы можете объявить 'private static readonly object _lockObject = new object();' в 'GenericClass ', что дает вам другой объект блокировки для каждого 'T'. –

0

Если вы используете дженерик, то что-то вроде

public class MyGadget<T> 
{ 
    static readonly SyncRoot = new object() ; 

    public T SynchronizedMethod() 
    { 
    lock (SyncRoot) 
    { 
     SynchronizedMethodGuts() ; 
    } 
    } 

} 

должен делать то, что вы хотите, потому что MyGadget<Foo> и MyGadget<Bar> являются различными классами: каждый из них имеет свое собственное, отличную SyncRoot поля.

+0

Это интересная идея и может даже работать в моей ситуации. Разница в том, что мой «общий» знает, как выполнять определенные операции, не требуется никаких экземпляров. Здесь мне нужен экземпляр. Я просто думаю, что это слишком много для меня, а не для истинной причины. –

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