这是一个体面的自制互斥实现吗?批评?潜在问题?

时间:2013-08-05 06:13:48

标签: c mutex

我想知道是否有人看到任何可能导致此代码出现问题的内容。我知道还有其他方法/ API调用,我可以用来做到这一点,但我试图为我自己的平台独立奠定基础? /跨平台互斥框架。

显然我需要做一些#ifdef并为Win32 Sleep()和GetCurrentThreadID()调用定义一些宏......

typedef struct aec {
    unsigned long long lastaudibleframe; /* time stamp of last audible frame */
    unsigned short aiws; /* Average mike input when speaker is playing */
    unsigned short aiwos; /*Average mike input when speaker ISNT playing */
    unsigned long long t_aiws, t_aiwos; /* Internal running total */
    unsigned int c_aiws, c_aiwos; /* Internal counters */
    unsigned long lockthreadid;
    int stlc; /* Same thread lock count */
} AEC;

char lockecho( AEC *ec ) {
    unsigned long tid=0;
    static int inproc=0;
    while (inproc) {
        Sleep(1);
    }
    inproc=1;
    if (!ec) {
        inproc=0;
        return 0;
    }
    tid=GetCurrentThreadId();
    if (ec->lockthreadid==tid) {
        inproc=0;
        ec->stlc++;
        return 1;
    }
    while (ec->lockthreadid!=0) {
        Sleep(1);
    }
    ec->lockthreadid=tid;
    inproc=0;
    return 1;
}

char unlockecho( AEC *ec ) {
    unsigned long tid=0;
    if (!ec)
        return 1;
    tid=GetCurrentThreadId();
    if (tid!=ec->lockthreadid)
        return 0;
    if (tid==ec->lockthreadid) {
        if (ec->stlc>0) {
            ec->stlc--;
        } else {
            ec->lockthreadid=0;
        }
    }
    return 1;
}

2 个答案:

答案 0 :(得分:3)

不,不是,AFAIK如果没有一些低级atomic操作(RMWTest and Set等等),您无法使用纯C代码实现互斥锁。你的特定例子,考虑如果上下文切换在有机会设置inproc之前中断第一个线程会发生什么,然后第二个线程将恢复并将其设置为1,现在两个线程都“认为”他们拥有对结构的独占访问权限......这只是你的方法可能出错的许多事情之一。

另请注意,即使线程有机会设置inproc,也不保证赋值是原子的(在分配变量的过程中可能会中断)。

答案 1 :(得分:1)

正如mux指出的那样,由于许多竞争条件,您提出的代码不正确。您可以使用像“比较和设置”这样的原子指令来解决这个问题,但无论如何您都需要为每个平台单独定义。您最好只定义一个高级“锁定”和“解锁”界面,并使用平台提供的任何内容实现那些