假设我编写了一个 C++ 信号量类,其接口(interface)模拟了 boost Lockable 概念(即 lock(); unlock(); try_lock();
等)。对此类对象的 RAII 访问使用升压锁是否安全/推荐?换句话说,boost 锁(和/或 boost 线程库的其他相关部分)是否假设 Lockable 概念将仅由从同一线程锁定和解锁的类似互斥锁的对象建模?
我的猜测是使用信号量作为 Lockable 的模型应该没问题。我浏览了一些增强源,它“似乎”没问题。这些锁似乎没有存储对 this_thread 或类似内容的显式引用。此外,Lockable 概念没有像whichThreadOwnsMe()
这样的功能。 .看起来我什至应该能够通过 boost::unique_lock<MySemaphore>
引用boost::condition_variable_any::wait
.但是,文档并未明确说明这些要求。
为了说明我的意思,考虑一个基本的二进制信号量类:
class MySemaphore{
bool locked;
boost::mutex mx;
boost::condition_variable cv;
public:
void lock(){
boost::unique_lock<boost::mutex> lck(mx);
while(locked) cv.wait(lck);
locked=true;
}
void unlock(){
{
boost::lock_guard<boost::mutex> lck(mx);
if(!locked) error();
locked=false;
}
cv.notify_one();
}
// bool try_lock(); void error(); etc.
}
现在假设在某处,无论是在一个对象上还是在全局范围内,我有
MySemaphore sem;
我想使用 RAII 锁定和解锁它。此外,我希望能够将锁的所有权从一个线程“传递”到另一个线程。例如,在我执行的一个线程中
void doTask()
{
boost::unique_lock<MySemaphore> lock(sem);
doSomeWorkWithSharedObject();
signalToSecondThread();
waitForSignalAck();
lock.release();
}
当另一个线程正在执行类似的东西时
{
waitForSignalFromFirstThread();
ackSignal();
boost::unique_lock<MySemaphore>(sem,boost::adopt_lock_t());
doMoreWorkWithSameSharedObject();
}
我这样做的原因是我不希望任何其他人能够锁定 sem
在第一个线程执行 doSomeWorkWithSharedObject()
之间和第二个执行的时间 doMoreWorkWithSameSharedObject()
.基本上,我将一项任务分成两部分。我将任务拆分的原因是(1)我希望任务的第一部分尽快开始,(2)我想保证第一部分在 doTask() 返回之前完成, (3) 我希望任务的第二个、更耗时的部分由另一个线程完成,可能是从等待完成由主线程启动的任务的从属线程池中选择的。
注意:我最近在这里发布了同样的问题(有点)Modelling boost::Lockable with semaphore rather than mutex (previously titled: Unlocking a mutex from a different thread) 但我混淆了互斥锁和信号量,所以关于使用升压锁的问题并没有真正得到解决。
最佳答案
@dan,我觉得你把事情搞得太复杂了。您所描述的内容可以通过主处理线程、同步队列和工作线程[池]轻松实现。您似乎也落入了使用锁来“保护代码”的常见陷阱,而这是您需要保护的数据结构。
定义您的共享数据,在数据可能不一致时识别最小关键部分。用锁支撑那个。
关于c++ - 使用升压锁进行 RAII 对信号量的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2755720/