C++ 这是C++;信号灯?
我有一个线程保存资源(设备的OpenCl命令队列),但我想限制同时访问此资源的线程数(如果gpu命令队列“已满”,我想在cpu上计算)。不幸的是,我对c++11原子操作还比较陌生。所以我想知道下面的源代码是否按预期工作C++ 这是C++;信号灯?,c++,multithreading,c++11,atomic,C++,Multithreading,C++11,Atomic,我有一个线程保存资源(设备的OpenCl命令队列),但我想限制同时访问此资源的线程数(如果gpu命令队列“已满”,我想在cpu上计算)。不幸的是,我对c++11原子操作还比较陌生。所以我想知道下面的源代码是否按预期工作 class SpinSemaphore{ public: SpinSemaphore(int max_count): _cnt(0), _max_cnt(max_count){} bool try_lock(){ boo
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
}
类自旋信号量{
公众:
自旋信号量(int max_count):
_碳纳米管(0),
_max_cnt(max_count){
bool try_lock(){
bool run=true;
while(运行){
int cnt=_cnt.load();
如果(++cnt>\u max\u cnt)返回false;
run=!std::原子比较交换弱,
std::存储器(顺序获取);
}
返回true;
}
无效解锁(){
--_碳纳米管;
}
私人:
std::原子碳纳米管;
int_max_cnt;
};
//
自旋信号量m(4);
void foo(){/。。
如果(m.try_lock()){/。。
my_queue.enqueueNDRangeKernel(/**/);
}
其他的
//退路
}
< /代码> 不,这不会像预期的那样行动——考虑2个线程到达的情况。
int cnt=_cnt.load()代码>同时。它们都将读取相同的值,并且都将计数器设置为相同的值,即使它们中可能只有一个应该得到相同的值
这可能被认为是一个可以接受的罕见事件,你可以忽略,除了当你解锁,你的计数将变成负数 可能是因为输入错误,但您使用原子\u比较\u交换\u弱()是错误的
你需要的是
do {
old=_cnt.load();
new=old+1;
if (new > _max_cnt) return false;
} while (!_cnt.compare_exchange_weak(&old,new));
将obj.compare_exchange_weak(旧的、新的)想象成一个原子-compare_和-Swap()函数
“多读卡器;无写卡器”-不需要锁定,然后就可以了?目的是限制读卡器的数量。我把话题改成在下面划线,然后你要的是一个信号灯。一个使用std::condition的impl——在C++11中是可用的——很抱歉,看起来是这样的。我弄糊涂了。有没有办法修复ittry int cnt=++\u cnt,它将保留该值,如果失败,您可以“解锁”。这也不是完美的,因为如果一个线程尝试锁定,一个线程解锁,另一个线程锁定,结果可能是两个线程都无法获得锁,但它至少可以确保您不会向太多线程提供锁。
bool Compare_And_Swap() {
if (obj == old) {
obj = new;
return true;
}
return false;
}