2013-12-20 5 views
3

В C++ меня учат использовать ключевое слово volatile для переменной (myVar), которое используется из разных потоков даже в критической секции. Но для C# я читал в MSDN эту странную фразу: «Модификатор volatile обычно используется для поля, к которому обращаются несколько потоков, не используя оператор блокировки для сериализации доступа». Имеет ли эта фраза, что если я под замком, вам не нужно использовать ключевое слово volatile? Если да, то еще один вопрос: может быть, я должен заблокировать эту переменную (myVar)?volatile ключевое слово в C# и C++

Object a = new Object(); 
double i,k; 
Thread1() 
{ 
    lock(a) 
    { 
     i++;// using variable i. 
     k++;// using variable k. 
    } 
} 

Thread2 сделать то же самое. Безопасно, что я и к не летучий, или я должен сделать так ?:

lock(i) 
{ 
    i++;// using variable i. 
} 
lock(k) 
{ 
    k++;// using variable k. 
} 
+0

Дубликат http://stackoverflow.com/a/1682309/2958164 –

+0

начните с [старого блога Эрика Липперта] (http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/ atomicity-volatility-and-immutability-are-different-part-three.aspx) – Mgetz

+0

Узнайте, что на самом деле делает 'volatile' на C++ (http://stackoverflow.com/questions/6866206/volatile-and-createthread/6866927# 6866927). Очень отличается от вашего понимания. Его полезность ограничена. –

ответ

3

В стандартном C++ volatile не имеет ничего общего с потоками, хотя, очевидно, компилятор Microsoft дает ему какое-то особое значение. Для таких вещей, как счетчики, используйте std::atomic<int>; нет необходимости в отдельных замках.

+0

Btw, существуют псевдонимы типов для некоторых из них: 'std :: atomic_int'. – chris

+0

@chris - существуют typedef для всех интегральных типов, в основном для взаимодействия с C. –

0

Правильно, в C# под lock вам не нужно использовать volatile, так как при использовании lock гарантирует, что все потоки будут видеть самое современное значение.

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

Ваш второй вопрос невозможен - у вас есть lock по ссылочному типу - предположим, что вы сделали, однако в обоих случаях операция «поточно-безопасная» при условии, что все остальные чтения и записи блокируются в одном экземпляре , как правило, более гранулированный объект лучше, поэтому вам не нужно заставить другие потоки ждать, когда они захотят обновить что-то еще, и им придется получить тот же замок, но вы можете знать, что эти вары всегда доступны вместе, и в этом случае совместная блокировка будет быть более эффективным.

+0

Итак, в моем примере безопасно ли использовать блокировку (a) для обеих переменных i и k? – user3121273

+0

ваш второй поток должен блокировать один и тот же объект, т. Е. Блокировать (a) {I ++; k ++}, тогда это так. – markmnl

+0

@ user3121273 как правило, всегда блокируется при доступе к var в том же экземпляре, что и другие блокировки, и вы не можете ошибиться, не нужно беспокоиться ни о чем другом, например. volatile ... :) – markmnl

6

В C++ я учил использовать энергонезависимую ключевое слово переменной (MYVAR), который используется из разных потоков даже в критической секции

Кто бы научил вас это не учит вас всю историю. Волатильность в C++ не гарантирует, что чтение или запись приобретают или освобождают семантику! Все летучие гарантии заключаются в том, что компилятор не будет генерировать код, который будет считывать или читать и записывать не в порядке. Недостаточно энергопотребления для обеспечения правильной семантики многопоточности, если ваш компилятор не предъявляет дополнительные требования о том, что для него означает «изменчивость».

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

Правильно. в C#, летучий делает ввести приобретают и освобождение семантики, вставив соответствующую половину забора. Поскольку замок представляет полный забор, летучий ненужно при чтении поля в замке.

Может быть, я должен заблокировать эту переменную (myVar)?

Весь этот код настолько сломан и ошибочен, что невозможно ответить на вопрос. ++ опасен для парных, что делает double volatile даже не законным в C#, и вы не можете блокировать типы значений.

+0

«volatile не требуется при чтении поля в замке», я всегда задавался вопросом: это деталь реализации или это в спецификации? – markmnl

+0

@markmnl: Спецификация C# тщательно описывает взаимосвязь между изменчивым и блокирующим. Если этот вопрос вас интересует, я рекомендую вам ознакомиться с спецификацией. –

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