Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Про Interlocked фунцкии


Автор: 0xDEAD 11.9.2011, 20:40
Добрый день.

Я тут читаю про синхронизацию между потоками процесса, и на msdn есть такой пример:
http://msdn.microsoft.com/en-us/library/ms686355(VS.85).aspx

Они пишут что так писать не thread-safe:
Код

int iValue;
BOOL fValueHasBeenComputed = FALSE;
extern int ComputeValue();

void CacheComputedValue()
{
  if (!fValueHasBeenComputed) 
  {
    iValue = ComputeValue();
    fValueHasBeenComputed = TRUE;
  }
}
 
BOOL FetchComputedValue(int *piResult)
{
  if (fValueHasBeenComputed) 
  {
    *piResult = iValue;
    return TRUE;
  } 

  else return FALSE;
}


И по этому лучше писать так:
Код

int iValue;
BOOL fValueHasBeenComputed = FALSE;
extern int ComputeValue();

void CacheComputedValue()
{
  if (InterlockedCompareExchange((LONG*)&fValueHasBeenComputed, 
          (LONG) fValueHasBeenComputed, 
          (LONG) fValueHasBeenComputed)==FALSE) 
  {
    InterlockedExchange ((LONG*)&iValue, (LONG)ComputeValue());
    InterlockedExchange ((LONG*)&fValueHasBeenComputed, TRUE);
  }
}
 
BOOL FetchComputedValue(int *piResult)
{
  if (InterlockedCompareExchange((LONG*)&fValueHasBeenComputed, 
          (LONG) fValueHasBeenComputed, 
          (LONG) fValueHasBeenComputed)==TRUE) 
  {
    InterlockedExchange((LONG*)piResult, (LONG)iValue);
    return TRUE;
  } 

  else return FALSE;
}


Зачем нужны InterlockedExchange мне понятно, но вот насчет InterlockedCompareExchange...
Во первых, по моему это по мухе с пулемета, и сравнивать и писать то же значение только для того, чтобы еще раз сравнить.
Во вторых, нужно ли оно тут вообще?
if(fValueHasBeenComputed) ведь только один раз читает память, что есть, как я понимаю, атомная операция.

Автор: volatile 12.9.2011, 00:24
Цитата(0xDEAD @  11.9.2011,  20:40 Найти цитируемый пост)
лучше писать так:

Если внимательно почитать статью, то так писать лучше лишь в 2003 студии.
А в 2005 уже можно писать без InterlockedExchange, достаточно только объявить переменные volatile.
Цитата

With Visual Studio 2005, the compiler uses acquire semantics for read operations on volatile variables and release semantics for write operations on volatile variables (when supported by the CPU).


Если у вас 2003, стоит задуматься над переходом на более свежую версию компилятора.

Автор: 0xDEAD 28.9.2011, 10:39
Хм, я не совсем понимаю.
Написано:
* the compiler will not re-order volatile variable access. However, these operations could be re-ordered by the processor.
* With Visual Studio 2005, the compiler uses acquire semantics for read operations on volatile variables and release semantics for write operations on volatile variables.

То есть:
* Компилятор компилирует volatile в точно такой же последовательности, как написано в коде. Но несмотря на это, процессор может изменить эту последовательность.
* VS 2005 использует acquire/release semantics (если я правильно понял, речь о LOCK командах) с volatile.

Так вот, я пользуюсь VS 2010. Я скомпилировал первый код, с volatile, но никаких LOCK-ов в компилированном коде нету.

Правильно ли я понимаю значение acquire/release semantics в тексте, и фразу "operations could be re-ordered by the processor"?

Автор: volatile 28.9.2011, 14:38
Цитата(0xDEAD @  28.9.2011,  10:39 Найти цитируемый пост)
если я правильно понял, речь о LOCK командах

Не обязательно.

Код

  The processor uses three interdependent mechanisms for  carrying  out  locked
atomic operations:
  • Guaranteed atomic operations
  • Bus locking, using the LOCK# signal and the LOCK instruction prefix
  • Cache coherency protocols that insure that atomic operations can be carried
out on cached data structures (cache lock); this mechanism is  present  in  the
Pentium 4, Intel Xeon, and P6 family processors


Цитата(0xDEAD @  28.9.2011,  10:39 Найти цитируемый пост)
но никаких LOCK-ов в компилированном коде нету.

Ну во-первых может быть, они в вашем конкретном случае и не нужны.  smile 
вот http://blogs.msdn.com/b/kangsu/archive/2007/07/16/volatile-acquire-release-memory-fences-and-vc2005.aspx объясняется подобный случай.

 

Автор: 0xDEAD 28.9.2011, 17:11
ОК, я понял что тема эта не простая.
Тут есть два понятия:
* Атомарность.
* Последовательность обновления значений для других процессоров.

volatile гарантирует последовательность обновления значений - то есть что iValue обновится перед fValueHasBeenComputed, а не наоборот.
А атомарность в этом случае гарантированна, потому что чтение/запись из/в выравненный DWORD есть "Guaranteed atomic operation".

Интересная ссылка:
http://stackoverflow.com/questions/5002046/atomicity-in-c-myth-or-reality

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)