2

我有一个程序,其中多个线程更新数组的值。

#include<windows.h>
#include<iostream>
#include<stdio.h>
HANDLE Mutex;
    int n = 100;
static DWORD WINAPI ThreadedUpdate(LPVOID param){
    DWORD GetMutex;
    GetMutex = WaitForSingleObject(Mutex,INFINITE);
    if(GetMutex == WAIT_ABANDONED){
        std::cout << "Error : Could not get Mutex for working Thread. " << std::endl;
        exit(0);
    }
    else if(GetMutex == WAIT_OBJECT_0){
        int* a = (int*) param;
        for(int i = 0 ; i < n ; i++)
            a[i] += 100;
    }
    if(!ReleaseMutex(Mutex)){
        std::cout << "Error : Could not relese Mutex." << std::endl;
        exit(0);
    }
    return 0;
}

int main(int argc, char** argv){
    int numThreads = 50;
    int* a = new int[n];
    HANDLE* Th = new HANDLE[numThreads];
    Mutex = CreateMutex(NULL,FALSE,NULL);
    DWORD t;
    for(int i = 0 ; i < n ; i++)
        a[i] = 0;
    for(int i = 0 ; i < numThreads ; i++)
        Th[i] = CreateThread(NULL,0,ThreadedUpdate,(void*)a,0,&t); 
    WaitForMultipleObjects(numThreads, Th, TRUE, INFINITE);
    for(int i = 0 ; i < n ; i++)
        std::cout << a[i] << std::endl;
    std::getchar();
}

现在,在上面的程序中,我使用互斥锁进行同步。但我观察到的是,即使我不使用同步,我得到的答案也是正确的。这是否意味着在这种情况下不需要锁。+= 运算符是原子的吗?这只是一个示例程序。我在机器学习算法中使用了类似的代码,其中多个线程正在更新一个向量。即使在那种情况下,我在不使用锁的情况下也能得到预期的输出。由于更新非常频繁,使用锁会使程序变得非常慢。我只是想确保如果我不使用锁会有什么问题吗?

4

1 回答 1

0

您不需要在此代码中使用互斥锁或临界区,只要多线程环境中的所有写入和读取都在原子操作下即可。

Windows 中的 Atomics 需要long参数,因此首先将数组更改为long而不是int. 然后,将线程过程更改为:

static DWORD WINAPI ThreadedUpdate(LPVOID param)
{
    for(int i = 0 ; i < n ; i++)
        InterlockedAdd((long*)param + i, 100);
    return 0;
}

用一些巨大的数组测试它,我认为它会做你想要的。你main()的减少到:

int main(int argc, char** argv)
{
    int numThreads = 50;
    long* a = new long[n];
    HANDLE* Th = new HANDLE[numThreads];

    for(int i = 0 ; i < n ; i++)
        a[i] = 0;

    for(int i = 0 ; i < numThreads ; i++)
        Th[i] = CreateThread(NULL,0,ThreadedUpdate, a, 0, NULL); 

    WaitForMultipleObjects(numThreads, Th, TRUE, INFINITE);

    for(int i = 0 ; i < n ; i++)
        std::cout << a[i] << std::endl;
    delete [] a;

    for (int i=0; i<numThreads; CloseHandle(Th[i++]));
    delete [] Th;

    std::getchar();
}
于 2013-11-01T18:22:09.120 回答