DWORD WINAPI ThreadProc(LPVOID lpParam);
void ErrorReport(LPTSTR lpszFunction);
int main()
{
DWORD dwThreadId;
HANDLE hThread, hSem, hMutex;
unsigned i;
// сигналды емес бастамамен семафор құрамыз
// мьютексті құруда процестерді синхрондау үшін
// осы семафор қолданылады if((hSem =
CreateSemaphore(NULL, 0, 1, "Threadl")) == NULL)
{
ErrorReport(TEXT("CreateSemaphore()")); return(1);
}
254
hThread = CreateThread(
NULL,
// әдеттегідей құқық // әдепкә
бойынша қамшы өлшемі
ThreadProc, // ағым функциясы
NULL,
// функция үшін
аргумент жоқ
0,
// әдеттегідей жалаушалар
&dwThreadId);
if(hThread == NULL)
{
ErrorReport(TEXT("CreateThread()"));
return(1);
}
// мьютексті еншілес етіп құру
// есептеуіш ағымымен WaitForSingleObject(hSem,
INFINITE);
// мьютекс құруда дескриптор аламыз if((hMutex =
OpenMutex(MUTEX_ALL_ACCESS, FALSE, "Thread2")) ==
NULL)
{
ErrorReport(TEXT("OpenMutex()"));
return(1);
}
// алғашқы ағымның негізгі циклі for(i = 0; i < 10;
++i)
{
// басқару жіберілімін күту
// туындаған ағымнан
WaitForSingleObject(hMutex, INFINITE);
// ақпараттарды консолды
шығару printf("p%d ", i);
// алғашқы ағымды 1 сек блоктау Sleep(1000);
// туындаған ағымның басқарылуын жіберу
ReleaseMutex(hMutex);
}
// туындаған ағымның аяқталуын күту
WaitForSingleObject(hThread, INFINITE);
// дескриптор жабу CloseHandle(hThread);
// семафор және мьютекстің дескрипторын жабу
CloseHandle(hSem);
CloseHandle(hMutex);
255
printf("\n");
return(0);
}
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
HANDLE hSem, hMutex; unsigned i;
// ертерек семафорын дескриптор алу if((hSem =
OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE,
"Thread1")) == NULL)
{
ErrorReport(TEXT("OpenSemaphore()")); return(1);
}
// бастапқы сигналды емес мьютексті құру
//
if((hMutex =CreateMutex(NULL, FALSE, "Thread2")) ==
NULL)
{
ErrorReport(TEXT("CreateMutex()"));
return(1);
}
// семафорды сигналды күйге ауыстыру
// ақпаратты шығаруды синхрондау үшін мьютексты
құрылуы туралы алғашқы ағымына хабарлау
// ReleaseSemaphore(hSem, 1, NULL);
// еншілес ағымның негізгі циклі
for(i = 0; i < 10; ++i)
{
// бастапқы ағымның басқаруды жіберуін күту
//
WaitForSingleObject(hMutex, INFINITE);
// ақпараттарды
консолға шығару
printf("c%d ", i);
// ағымды 4 секундқа
блоктауSleep(4000);
// алғашқы ағымға басқаруды жібереміз
ReleaseMutex(hMutex);
}
// семафор мен мьютекстің дескрипторын жабамыз
CloseHandle(hSem);
256
CloseHandle(hMutex); return(0);
}
void ErrorReport(LPTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
&lpMsgBuf,
0, NULL );
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)
lpszFunction)+40)*sizeof(TCHAR));
_stprintf((LPTSTR)lpDisplayBuf,
TEXT("%s failed with error %d: %s"), lpszFunction,
dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf,
TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
Берілген үлгіде семафор тек процестердің алғашқы синхрондау
үшін қолданылады.
Семафордың көмегімен, еншілес ағым алғашқы
ағымға
мьютекстің құрылуын хабарлайды, ол алғашқы және еншілес
есептеуіш ағымдарды консолға
қол жеткізуін болдырмауды
ұйымдастырады. Ары қарай семафор қолданылмайды,
тек мьютекс
қолданылады.
Берілген бағдарламаның жұмысы нәтижесінде консолға келесі жол
шығады:
c0 p0 cl pi c2 p2 c3 p3 c4 p4 c5 p5 c6 p6 c7 p7 c8 p8 c9
р9
257
Алдындағыдай, екі ағым үйлестірілген және олардың шығуы қатаң
кезектеседі. Егер де жоғарыда келтірілген бағдарламаға ResetMutex()
және WaitForSingleObjectQ функцияларының шақыртуларында ішкі
циклдері
және бастапқы ағым, ағым тобын түсіндіре кетсек,
бағдарлама жұмысының нәтижесі мынадай болады:
c0 p0 pl p2 p3 cl p4 p5 p6 p7 p8 c2 p9 c3 c4 c5 c6 c7 c8
c9
Мұнда тағы жағдай қайталанады, ағымдардың синхрондауы
жүргізілмесе бастапқы ағым өзінің жұмысын
еншілес ағымнан бұрын
аяқтайды және консолға ақпараттарды шығарғанда екі есептеуіш
ағымдар синхрондалмайды.
Достарыңызбен бөлісу: