Проверка необходимости блокировки синхронизации примитивных типов данных с C ++

0

Я вижу много потоков на этом форуме, занимающихся вопросом, нужно ли нам использовать синхронизацию при доступе к примитивным типам данных из нескольких потоков: вопрос 1, вопрос 2, вопрос 3, вопрос 4...

Поэтому я написал небольшой тест, чтобы проверить это:

Я запускал его более часа на процессоре Intel(R) Core(TM) i7 CPU 860 @2.80GHz который работает с 4 физическими ядрами:

#define MULTIPLIC_VAL 17

DWORD gdwSharedVal01 = MULTIPLIC_VAL;

DWORD WINAPI thread001(LPVOID lpParameter);

//Begin threads
for(int i = 0; i < 30; i++)
{
    DWORD dwThreadId;
    HANDLE hThread = ::CreateThread(NULL, 0, thread001, NULL, 0, &dwThreadId);
    if(hThread)
    {
        ::CloseHandle(hThread);
    }
    else
    {
        _tprintf(L"ERROR: CreateThread error %d\n", ::GetLastError());
    }
}

//Wait
getchar();


BOOL checkSharedValue()
{
    //RETURN:
    //      = TRUE if value is OK
    if((gdwSharedVal01 % MULTIPLIC_VAL) == 0)
    {
        return TRUE;
    }

    return FALSE;
}


DWORD WINAPI thread001(LPVOID lpParameter)
{
    srand((UINT)time(NULL));

    DWORD dwThreadID = ::GetCurrentThreadId();
    _tprintf(L"Thread %d began...\n", dwThreadID);

    for(;;)
    {
        //Set value
        DWORD v = rand();
        v <<= 16;
        v ^= rand();

        v = v / MULTIPLIC_VAL;
        gdwSharedVal01 = v * MULTIPLIC_VAL;

        //Check value
        if(!checkSharedValue())
        {
            //Failed
            _tprintf(L"FAILED thread %d\n", dwThreadID);
        }
    }

    return 0;
}

и я не потерпел неудачу. Итак, как бы вы это объяснили?

  • 0
    Некоторые процессоры, примером которых является x86, гарантируют многопоточным программам гораздо больше, чем другие процессоры или стандарты C или C ++.
  • 0
    Я бы объяснил это тем, что иногда результатом неопределенного поведения является то, что вы ожидаете.
Теги:
multithreading
synchronization

1 ответ

2
Лучший ответ

В Intel чтение и запись для выровненных слов - это атомные операции (атомарные в том смысле, что другие процессоры будут видеть либо оригинал, либо новое значение).

Обратите внимание, что это не означает, что вы не должны предоставлять механизм синхронизации. Этот тестовый пример - это тот, в котором потоки просто записывают и считывают новые значения в одну и ту же переменную. Если они выполняли какую-то операцию, связанную с чтением/записью для обновления, она могла потерпеть неудачу (скажем, что 10 потоков увеличивают эту переменную на 100, переменная в конце, возможно, не была увеличена на 1000 баллов!) И что нет другие переменные в игре (где переупорядочение компилятора/процессора может вызвать другие проблемы).

  • 0
    Ну да, конечно, если тот же поток попытается прочитать из моей переменной gdwSharedVal01 после обновления, он не будет иметь того же значения. Моей главной заботой была целостность самого примитивного типа (за одну операцию).
  • 0
    Итак, скажем, если я точно знаю, что мой код будет работать на компьютере с архитектурой x86 / x64, работающей только под Windows, Windows XP и выше, могу ли я безопасно пропустить синхронизацию для примера, подобного приведенному выше?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню