ME>Приведи конкретный пример.
Сырец
// VolatileTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// Допустим флаг некоего потока (хотя конечно так лучше не делать)
//
int Variable1 = 0;
//
// Некоя переменная для вычислений. Допустим она используеться
// одновременно из нескольких потоков.
//
int Variable2 = 0;
int Thread()
{
while(Variable1 == 0)
{
Variable2 += 123;
if (++Variable2 > 6134)
{
Variable2 -= 534;
Variable2 *= Variable2;
}
else
{
Variable2 -= 32;
Variable2 += Variable2 / 2;
}
Sleep(1);
}
return 0;
}
void FireFlag()
{
Variable1 = 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
//
// Need to look generated assembler code in the release version
//
__asm int 3;
//
// Assume another thread here
//
Thread();
//
// Signal the Flag
//
FireFlag();
return 0;
}
Без волатайла
int Thread()
{
while(Variable1 == 0)
00401000 mov eax,dword ptr [Variable1 (4072C0h)]
00401005 test eax,eax
00401007 jne Thread+53h (401053h)
00401009 push esi
0040100A mov esi,dword ptr [__imp__Sleep@4 (405000h)]
{
Variable2 += 123;
if (++Variable2 > 6134)
00401010 mov ecx,dword ptr [Variable2 (4072C4h)] Один раз закешировали и начали использовать уже регистр
00401016 add ecx,7Ch
00401019 cmp ecx,17F6h
0040101F jle Thread+33h (401033h)
{
Variable2 -= 534;
00401021 sub ecx,216h
Variable2 *= Variable2;
00401027 mov eax,ecx
00401029 imul eax,ecx
0040102C mov dword ptr [Variable2 (4072C4h)],eax Слили в память только тут
}
else
00401031 jmp Thread+45h (401045h)
{
Variable2 -= 32;
00401033 sub ecx,20h
Variable2 += Variable2 / 2;
00401036 mov eax,ecx
00401038 cdq
00401039 sub eax,edx
0040103B sar eax,1
0040103D add ecx,eax
0040103F mov dword ptr [Variable2 (4072C4h)],ecx Слили в память только тут
}
Sleep(1);
00401045 push 1
00401047 call esi
00401049 mov eax,dword ptr [Variable1 (4072C0h)]
0040104E test eax,eax
00401050 je Thread+10h (401010h)
00401052 pop esi
}
return 0;
С волатайлом
int Thread()
{
while(Variable1 == 0)
00401000 mov eax,dword ptr [Variable1 (4072C0h)]
00401005 test eax,eax
00401007 jne Thread+86h (401086h)
00401009 push esi
0040100A mov esi,dword ptr [__imp__Sleep@4 (405000h)]
{
Variable2 += 123;
00401010 mov eax,dword ptr [Variable2 (4072C4h)]
00401015 add eax,7Bh
00401018 mov dword ptr [Variable2 (4072C4h)],eax
if (++Variable2 > 6134)
0040101D mov ecx,dword ptr [Variable2 (4072C4h)]
00401023 inc ecx
00401024 mov dword ptr [Variable2 (4072C4h)],ecx
0040102A cmp dword ptr [Variable2 (4072C4h)],17F6h
{
Variable2 -= 534;
00401034 mov edx,dword ptr [Variable2 (4072C4h)]
0040103A jle Thread+58h (401058h)
0040103C sub edx,216h
00401042 mov dword ptr [Variable2 (4072C4h)],edx
Variable2 *= Variable2;
00401048 mov eax,dword ptr [Variable2 (4072C4h)]
0040104D mov ecx,dword ptr [Variable2 (4072C4h)]
00401053 imul eax,ecx
}
else
00401056 jmp Thread+73h (401073h)
{
Variable2 -= 32;
00401058 sub edx,20h
0040105B mov dword ptr [Variable2 (4072C4h)],edx
Variable2 += Variable2 / 2;
00401061 mov eax,dword ptr [Variable2 (4072C4h)]
00401066 mov ecx,dword ptr [Variable2 (4072C4h)]
0040106C cdq
0040106D sub eax,edx
0040106F sar eax,1
00401071 add eax,ecx
}
Sleep(1);
00401073 push 1
00401075 mov dword ptr [Variable2 (4072C4h)],eax
0040107A call esi
0040107C mov eax,dword ptr [Variable1 (4072C0h)]
00401081 test eax,eax
00401083 je Thread+10h (401010h)
00401085 pop esi
}
return 0;
00401086 xor eax,eax
}
Вот и представь, что Thread, испольняется несколькими потоками... Выходит, что потоки узнают о изменениях переменной, только тогда, когда компилятор соизволит слить её в память, а он может этого неделать оочень долго... Почувствуйте разницу