2015-07-28 3 views
1

Я новичок в C# и хочу задать вам вопрос. Вопрос о «parallell обновление переменной»Confused about paralell update a variable

Мой код ниже:

private void Form1_Load(object sender, EventArgs e) 
{ 
    Control.CheckForIllegalCrossThreadCalls = false; 
    // --------------------------- 

    Thread tTrue = new Thread(new ThreadStart(TrueThread)); 
    tTrue.Start(); 

    Thread tFalse = new Thread(new ThreadStart(FalseThread)); 
    tFalse.Start(); 
} 

bool Start = false; 
bool value; 

void TrueThread() 
{ 
    while (true) 
    { 
     if (Start == true) 
     { 
      value = true; 
      break; 
     } 
    } 
} 

void FalseThread() 
{ 
    while (true) 
    { 
     if (Start == true) 
     { 
      value = false; 
      break; 
     } 
    } 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    MessageBox.Show(value.ToString()); 
} 

private void button2_Click(object sender, EventArgs e) 
{ 
    Start = true; 
} 

Код объясняю: Во-первых, когда мой запуск приложения -> звоните TrueThread и FalseThread При запуске TrueThread и FalseThread, они будут проверять Значение «Старт», когда переменная «Старт» станет «истиной» (по умолчанию false, при нажатии кнопки «2» будет установлено значение «истина»), TrueThread установит значение «значение» varibale в значение true, а FalseThread установит значение «значение» в значение false.

Но я смутился, какой поток будет запущен первым? и конечное значение «value» будет истинным или ложным? и почему ?

Нажмите Button1, чтобы увидеть результат

ответ

0

Без надлежащей синхронизации, нет никакого способа, чтобы дать определенный ответ на свой вопрос. Если вы не синхронизируете доступ к общим переменным и не обеспечиваете определенный порядок выполнения, вы не можете знать, какой поток будет выполняться первым, и какой поток сначала выполнит свою работу (даже если у них есть такие же простые тела, как в вашем примере). Это означает, что вы не можете достоверно предсказать конечное значение переменной value.

Этот же код может вести себя по-разному (и производить другой конечный результат) на разных аппаратных средствах на разных основных (и второстепенных) версиях Windows или действительно на одном и том же, но работает в разное время (в зависимости от того, сколько нагрузки система обрабатывает и т. д.)

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

В более сложной программе общая переменная (например, value в вашем коде) может быть установлена ​​на несколько потоков, и это может привести к недопустимому состоянию, если вы не синхронизируете свои потоки.

Рассмотрим (довольно простой) пример:

// thread 1 
value = true; 

// ... 

if (value == true) 
{ 
    // #1: at this point, thread 1 may get suspended; go to #2 

    // do something critical 
} 

// thread 2 
if (value == false) 
{ 
    // do something mutually exclusive, also critical 

    // #3: if value got changed to false after thread 1 enters the 'if' 
    // this code will also execute, even though it's mutually exclusive; 
    // we reached a bad state 
} 

// thread 3 
// #2: if this runs just at the "right" time, 'value' gets overwritten 
// while thread 1 is already inside the 'if'; go to #3 
value = false; 

Поскольку вы не можете точно сказать, когда value получает значение true или false, вы не можете гарантировать, что только одна из важных задач, будут выполнены. Вы должны синхронизировать доступ к value, чтобы убедиться, что, как только один поток задает его значение, другие threds видят последнее значение, а не что-то промежуточное.

Понятно, что этот пример несколько надуман, но он иллюстрирует одну возможную проблему (из многих) отсутствия правильной синхронизации. (В простой ситуации, подобной этой, с помощью lock будет решена проблема. Существуют также конкретные структуры данных, такие как BlockingCollection, ConcurrentDictionary и т. Д., Которые используются для обеспечения безопасного доступа к различным структурам данных по нескольким потокам.)

+0

Можете ли вы дать мне правильную синхронизацию в этой ситуации? –

+0

Спасибо @xxbbcc, я думаю, я должен изменить свое решение о многопоточности –

+0

@viclic Спасибо, что приняли мой ответ. Я предполагаю, что вы новичок в многопоточности - если да, подумайте, почему вы хотите использовать несколько потоков. Они редко просты в использовании в реальных приложениях. Я не пытаюсь сказать вам не использовать потоки, но если вы это сделаете, убедитесь, что вы понимаете, почему вы их используете.Если вы еще не прочитали его, прочитайте этот вопрос (особенно ответ Эрика Липперта): http://stackoverflow.com/questions/19382705/c-sharp-volatile-keyword-usage-vs-lock – xxbbcc