这是 C++ 信号量吗?

Is this a C++ Semaphore?

我有一个线程保存资源(设备的 OpenCl 命令队列),但我想限制同时访问此资源的线程数(我想计算我的 cpu 如果 gpu 命令队列是 'to full')。不幸的是,我对 C++11 原子操作比较陌生。所以我想知道以下源代码是否按预期工作。

class SpinSemaphore{
public:
    SpinSemaphore(int max_count):
       _cnt(0),
       _max_cnt(max_count){}

    bool try_lock(){
       bool run = true;
       while(run){
           int cnt = _cnt.load();
           if(++cnt > _max_cnt) return false;

           run = !std::atomic_compare_exchange_weak(&_cnt, &cnt,
            std::memory_order_acquire);
       }
       return true;
   }

void unlock(){
    --_cnt;
}

private:
   std::atomic<int>     _cnt;
   int              _max_cnt;
};

//

SpinSemaphore m(4);

void foo(){ //..
   if(m.try_lock()){//..
      my_queue.enqueueNDRangeKernel(/**/);
   }
   else
       //fallback

}

不,这不会像预期的那样运行 - 考虑 2 个线程到达的情况 int cnt = _cnt.load();同时。他们都将读取相同的值,并且都将计数器设置为相同的值,即使可能只有其中一个应该得到。

这可能被认为是您可以忽略的罕见事件,除了当您解锁时,您的计数将变为负数。

可能是打错了,但是你用 atomic_compare_exchange_weak() 错了

你需要的是

do {
   old=_cnt.load();
   new=old+1;
   if (new > _max_cnt) return false;
} while (!_cnt.compare_exchange_weak(&old,new));

将obj.compare_exchange_weak(旧的,新的)想象成一个atomic-Compare_And_Swap()函数

bool Compare_And_Swap() {
    if (obj == old) {
        obj = new;
        return true;
    }
    return false;
}