2014-02-04 6 views
0

Я работаю над классом, который создает и управляет несколькими соединениями сокета и который будет пересылать информацию, полученную от сокетов, к основному потоку и наоборот. Многопоточность, в которой я передаю так много информации, но и для меня (как и большинство вещей на C#), но мне нужно уточнить, что именно делают «блокировки».Что именно блокирует замок?

Когда я блокирую часть метода, это гарантирует, что ни один другой поток не сможет войти в этот раздел кода или он фактически предотвратит изменение всех переменных в этом разделе кода другими потоками независимо от того, где они происходят ?

Например:

public class TestLock 
{ 
    public volatile int a = 0; 
    public volatile int b = 2; 
    private object ALock = new Object(); 

    public TestLock() { } 

    public void UnlockEdit(int atemp, int btemp) 
    { 
     a = atemp; 
     b = btemp; 
    } 

    public void LockedEdit(int atemp, int btemp) 
    { 


     lock(ALock) 
     { 
      a = atemp; 
      b = btemp; 
     } 
    } 

    public int[] ReturnValues() 
    { 
     int[] ret = new int[2]; 

     lock (ALock) 
     { 
      ret[0] = a; 
      ret[1] = b; 
     } 

     return ret; 
    } 

} 

Если поток А вызывает метод «LockedEdit» и чуть-чуть достигает замка, прежде чем нить B входит в UnlockEdit. Что происходит? Будет ли блокировка предотвращать изменение резьбы B от a и b? И он будет блокироваться? Или блокировка применяется только к одной конкретной ветви кода? Или я должен применить один и тот же объект «блокировки» (ALock) к каждому методу чтения и записи для объектов, которые я хочу изменить и прочитать из нескольких потоков?

+0

Этот вопрос также может помочь вам: http://stackoverflow.com/questions/9621438/confusion-about-the-lock-statement-in-c-sharp/9621805#9621805 –

ответ

1

Оператор lock создает в вашем коде critical section. Это предотвращает ввод других потоков в код внутри скобок операторов блокировок. Другие темы в основном ждут, пока настанет их очередь войти в раздел.

Он не мешает другим видам изменять переменные в классе. Например, TestLock.a и TestLock.b могут быть изменены функцией внутри класса TestLock, которая не использует оператор Lock (ALock). Кроме того, поскольку переменные a и b являются общедоступными, они могут быть изменены кодом вне класса (в отдельном потоке).

Вот хорошая ссылка на .NET Basic Threading:

ОТ MSDN:

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

Вот пример некоторого кода, который хранит переменные безопасные для многопоточных приложений (Взято из C# 3.0 cookbook):

public static class SaferMemberAccess 
     { 

      private static int numericField = 1; 
       private static object syncObj = new object(); 

      public static void IncrementNumericField() 
      { 
        lock(syncObj)    
         { 
         ++numericField; 
        } 
      } 

      public static void ModifyNumericField(int newValue) 
      { 
        lock(syncObj)    
         { 
         numericField = newValue; 
        } 
      } 

      public static int ReadNumericField() 
      { 
        lock (syncObj)    
         { 
         return (numericField); 
        } 
      } 
     } 
+0

Если я использую тот же «объект», - как «ALock» в приведенном выше коде - в двух разных замках будет активен только один замок за раз? И.Е. Если Thread A ввел блокировку в «LockedEdit», а Thread B называет «ReturnValues», поток B ждет блокировки Thread A для выпуска? – ThisHandleNotInUse

+1

Да Thread B будет ждать, когда Thread A выйдет из блокировки от LockedEdit –

+0

Большое спасибо - это было в значительной степени связано с тем, что я не делал, потому что пытался выяснить, как я буду модифицировать и/или читать один и тот же объект по-разному, если бы я мог блокировать только один метод за раз, чтобы изменить его. – ThisHandleNotInUse

1

Вы приобретающих замок на объекте, как вы делали здесь

lock(ALock) 

этот раздел кода теперь заблокирован этим объектом, и ни один другой объект не может войти в него до тех пор, пока блокировка не будет освобождена, т. Е. Этот объект покидает критический раздел.

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

7

Когда я блокирую часть метода, это гарантирует, что ни один другой поток не может войти в этот раздел кода или он фактически предотвратит изменение всех переменных в этом разделе кода другими потоками независимо от того, где они происходят?

Этот вопрос настолько сложный и плохо сформированный, что на него невозможно ответить. Давайте перепишем его.

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

Да. Более точный способ указать, что, однако, сказать: заблокированная секция не может быть введена до тех пор, пока не будет получен замок, связанный с объектом «монитор», заданным для оператора lock. Этот замок может быть получен только одним потоком за раз.

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

Когда я запирать раздел метода делает его только гарантировать, что никакой другой поток не может войти в этот раздел кода?

Нет. У блокировки есть другие действия, чем просто обеспечение взаимного исключения на блоке. Например, он вводит барьер памяти.

действительно ли это предотвращает изменение всех переменных в этом разделе кода другими потоками независимо от того, где они происходят?

Наверняка нет!

Будет ли блокировка предотвращать резьбу B от модификации a и b?

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

И будет ли он блокироваться?

Будет ли какой блок?

делает ли замок применимым только к одной конкретной ветви кода?

Я не могу понять этот вопрос.

Следует ли применять один и тот же объект «блокировки» (ALock) к каждому методу чтения и записи для объектов, которые я хочу изменить и прочитать из нескольких потоков?

Да.

вопрос вы не спросили, но должны иметь:

Должен ли я использовать многопоточность разделяемой памяти в первую очередь?

Возможно, нет. Очень сложно даже экспертам понять это правильно.Если бы я выполнял программирование сокетов, я бы начал с использования async-ожидания или параллельной библиотеки задач для управления моей асинхронностью, а не для вечеринки по потокам напрямую. Нитки - инструмент очень низкого уровня, предназначенный для экспертов; попытайтесь поднять уровень абстракции на несколько уровней.

+0

Извините, я имел в виду «делает это _only_, чтобы он не входил в этот раздел кода». Например, один и тот же фиксирующий «объект» используется для двух замков. Я читаю документацию, или у меня было бы гораздо больше вопросов, чем я делаю до сих пор. Иногда документация немного неясна для меня. Я действительно не знаю, что сбивало с толку о первом вопросе. Хотя я полагаю, что местоимение «они», что означает «переменные», было немного расплывчатым, поскольку оно могло ссылаться на «потоки». Что касается вашей метафоры в зубной пасте: я не знал, что именно сделал метод блокировки. – ThisHandleNotInUse

+0

@ThisHandleNotInUse: Ответ на первый вопрос, как вы написали, это «нет». Как это было бы полезно для вас? –

+1

"* Да. Подумайте о том, чтобы прочитать документацию, это то, о чем говорит документация. *« За исключением неверной документации и правильного ответа «нет». Другие потоки * могут * обращаться к тому же разделу кода, например, введя этот раздел кода, используя * другую * блокировку. (Например, если блокировка передается как параметр в код.) –

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