В WinAPI есть пара функций WaitForSingleObject() и ReleaseMutex(). Также существует семейство функций Interlocked *(). Я решил проверить производительность между захватом одного мьютекса и обменом переплетенной переменной.WaitForSingleObject vs Interlocked *
HANDLE mutex;
WaitForSingleObject(mutex, INFINITE);
// ..
ReleaseMutex(mutex);
// 0 unlocked, 1 locked
LONG lock = 0;
while(InterlockedCompareExchange(&lock, 1, 0))
SwitchToThread();
// ..
InterlockedExchange(&lock, 0);
SwitchToThread();
Я измерил производительности между этими двумя методами и выяснили, что использование взаимно сблокированы *() составляет около 38% быстрее. Почему это так?
Вот мой тест производительности:
#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
LONG interlocked_variable = 0; // 0 unlocked, 1 locked
int run = 1;
DWORD WINAPI thread(LPVOID lpParam)
{
while(run)
{
while(InterlockedCompareExchange(&interlocked_variable, 1, 0))
SwitchToThread();
++(*((unsigned int*)lpParam));
InterlockedExchange(&interlocked_variable, 0);
SwitchToThread();
}
return 0;
}
int main()
{
unsigned int num_threads;
cout << "number of threads: ";
cin >> num_threads;
unsigned int* num_cycles = new unsigned int[num_threads];
DWORD s_time, e_time;
s_time = GetTickCount();
for(unsigned int i = 0; i < num_threads; ++i)
{
num_cycles[i] = 0;
HANDLE handle = CreateThread(NULL, NULL, thread, &num_cycles[i], NULL, NULL);
CloseHandle(handle);
}
_getch();
run = 0;
e_time = GetTickCount();
unsigned long long total = 0;
for(unsigned int i = 0; i < num_threads; ++i)
total += num_cycles[i];
for(unsigned int i = 0; i < num_threads; ++i)
cout << "\nthread " << i << ":\t" << num_cycles[i] << " cyc\t" << ((double)num_cycles[i]/(double)total) * 100 << "%";
cout << "\n----------------\n"
<< "cycles total:\t" << total
<< "\ntime elapsed:\t" << e_time - s_time << " ms"
<< "\n----------------"
<< '\n' << (double)(e_time - s_time)/(double)(total) << " ms\\op\n";
delete[] num_cycles;
_getch();
return 0;
}
Мьютекс - это объект ядра для кросс-технологической синхронизации, поэтому каждая блокировка/разблокировка включает контекстный переключатель. [См. Здесь] (http://msdn.microsoft.com/en-us/magazine/cc163726.aspx) для соответствующего обсуждения. –
Насколько я знаю, Mutex больше подходит для синхронизации между несколькими процессами. Вы также можете попробовать критический раздел. – Paul
Как вы оценили производительность? Были ли какие-либо фактические споры на замках? –