2012-02-15 2 views
1

У меня есть следующий сценарий в моем коде (C# .NET 4):синхронизация вопрос

У меня есть логические переменный, которая инициализируется ложь:

bool b = false; 

теперь я создание экземпляра количества потоков, что каждый из них должен прочитать значение b. первый поток для чтения b - должен изменить его значение на true (и сделать некоторую логику ...), а остальные ничего не должны делать. Нужно ли использовать механизм синхронизации для «b» при чтении его значения, или я могу заблокировать его только при установке его значения в true? Это должно повысить свою производительность, но мне интересно, идентификатор его безопасный ..

+0

На каком языке это? – Tudor

ответ

5

Так требования:

  • несколько потоков чтения одного bool переменной
  • если нить видит значение false это должно изменить его true и выполнить дополнительную работу
  • если нить видит значение true, то ничего не должно произойти
  • только один поток должен быть BLE, чтобы изменить значение и выполнить дополнительную работу

Так что код будет выглядеть следующим образом:

public class Example 
{ 
    private bool b = false; 

    public void DoSomething() 
    { 
    if (!b) 
    { 
     b = true; 
     DoExtraStuff(); 
    } 
    } 
} 

Это, конечно, не является безопасным, если есть несколько потоков, исполняющих DoSomething и намерение состоит в том, что DoExtraStuff должен выполняться только один раз. Проблема в том, что потоки будут гоняться за чтением и записью b.

Вам действительно нужно сделать чтение и запись в b атомарным. Это можно сделать, используя ключевое слово lock.

public class Example 
{ 
    private bool b = false; 
    private object locker = new object(); 

    public void DoSomething() 
    { 
    bool trigger = false; 
    lock (locker) 
    { 
     if (!b) 
     { 
     b = true; 
     trigger = true; 
     } 
    } 

    if (trigger) 
    { 
     DoExtraStuff(); 
    } 
    } 
} 

Существует альтернативный шаблон с использованием CAS операции с помощью Interlocked.CompareExhange. К сожалению, нет перегрузки, которая принимает bool, но если вы хотите изменить это bool на int, то также будет работать следующее.

public class Example 
{ 
    private int b = 0; 

    public void DoSomething() 
    { 
    if (Interlocked.CompareExchange(ref b, 0, 1) == 0) 
    { 
     DoExtraStuff(); 
    } 
    } 
} 
+0

Вы правы. Более чем один поток может видеть '! B' как истинный и будет вводить if-block. – Ajay

+0

Да, вы правы, это правильная версия. Надеемся, что OP придет и изменит принятый ответ, чтобы я мог удалить свой ответ. Кажется, я неправильно понял, что он хотел сделать. – Tudor

+0

@Tudor: Да, непонимание вопросов со мной очень много. Формулировка этого вопроса могла бы быть немного лучше. –

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