如何使用win32从多线程上下文初始化线程基元?

时间:2014-01-15 07:41:51

标签: c++ c windows multithreading

我想创建一个静态锁

void foo(){
    static CRITICAL_SECTION *lock = NULL; //this is the problem, I cannot create any primitive to do this with win32 threads
    static long isInitialized = 0;
    if (InterlockedExchange(&isInitialized, 1) == 0){ //this will ensure that lock is initialized only once
        lock = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION));
        InitializeCriticalSection(lock);
    }
    EnterCriticalSection(lock); //this might be called before initialization is done...YIKES!
    ...
    LeaveCriticalSection(lock); 
}

如何从多线程上下文初始化锁?

糟糕的解决方案可能如下:

void foo(){
    static CRITICAL_SECTION *lock = NULL; //this is the problem, I cannot create any primitive to do this with win32 threads
    static long isInitialized = 0;
    static volatile long isInitializeDone = 0;
    if (InterlockedExchange(&isInitialized, 1) == 0){ //this will ensure that lock is initialized only once
        lock = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION));
        InitializeCriticalSection(lock);
        isInitializeDone = 1;
    } else {
        while (isInitializeDone == 0){

        }
    }
    EnterCriticalSection(lock); //this might be called before initialization is done...YIKES!
    ...
    LeaveCriticalSection(lock); 
}

但有更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

如果这是C ++,您可以调用函数来初始化该关键部分:

static CRITICAL_SECTION *lock = get_critical_section();

CRITICAL_SECTION* get_critical_section()
{
    CRITICAL_SECTION *lock = NULL;
    InitializeCriticalSection(&lock);
    return lock;
}

C ++指定只有一个线程将初始化该东西,并且所有其他线程将等待它:

[stmt.dcl]

如果控制进入 在初始化变量的同时声明,并发执行应该等待 完成初始化。

编辑:我不知道,因为标准中的文本是这样的,但我很确定这是所有实现的。

答案 1 :(得分:0)

另一种选择是利用这样一个事实:每个进程都有一个默认堆,其中包含一个已经初始化的关联锁:

void foo(void)
{
    static CRITICAL_SECTION lock;
    static DWORD lock_status = 0;

    if (lock_status == 0)
    {
        HANDLE process_heap = GetProcessHeap();
        if (!HeapLock(process_heap)) fail();

        if (lock_status == 0)
        {
            InitializeCriticalSection(&lock);
            lock_status = 1;
        }

        if (!HeapUnlock(process_heap)) fail();
    }
    EnterCriticalSection(&lock);
    // ...
    LeaveCriticalSection(&lock);
}