将pthread条件变量与rwlock一起使用 < >我想用一种方法来使用 pththrWLoCu条件C++中的例程>
我有两个问题: 第一:怎么可能?如果我们不能,为什么 第二:为什么当前的POSIX pthread没有实现这种行为 为了理解我的目的,我解释了我的用途:我有一个生产者-消费者模型来处理一个共享阵列。当数组为空时,使用者将进行cond_等待,但在读取某些元素时,使用者将进行rdlock。当从阵列中添加(+信号)或删除元素时,生产者将锁定将pthread条件变量与rwlock一起使用 < >我想用一种方法来使用 pththrWLoCu条件C++中的例程> ,c++,c,posix,pthreads,producer-consumer,C++,C,Posix,Pthreads,Producer Consumer,我有两个问题: 第一:怎么可能?如果我们不能,为什么 第二:为什么当前的POSIX pthread没有实现这种行为 为了理解我的目的,我解释了我的用途:我有一个生产者-消费者模型来处理一个共享阵列。当数组为空时,使用者将进行cond_等待,但在读取某些元素时,使用者将进行rdlock。当从阵列中添加(+信号)或删除元素时,生产者将锁定 使用rdlock而不是mutex\u lock的好处是提高性能:当使用mutex\u lock时,多个读卡器会阻塞,而使用rdlock时,多个读卡器不会阻塞。为了
使用rdlock而不是mutex\u lock的好处是提高性能:当使用mutex\u lock时,多个读卡器会阻塞,而使用rdlock时,多个读卡器不会阻塞。为了满足您的需要,您只需要有一组rwlock和一组mutex/cond变量伪代码(尽管您需要posix cond变量上的常规循环) 我猜条件变量只适用于互斥体,因为等待或发送条件需要相互排斥。我假设“条件”是指“条件变量”。它们是不同的东西 不,在等待条件变量时不能使用rwlock。我无法回答“为什么”,但POSIX决定这样做。也许只是为了简单起见 但是,通过只使用互斥锁和2个条件变量而不使用POSIX rwlock来创建自己的rwlock类,您仍然可以获得所需的行为:
getReadLock():
lock(mutex)
while(array.empty())
wait(readersCondVar, mutex)
readers++;
unlock(mutex)
releaseReadLock():
lock(mutex)
if (--readers == 0)
broadcast(writerCondVar, mutex) // or signal, if only 1 producer
unlock(mutex)
readerThread:
forever() {
getReadLock()
read()
releaseReadLock()
}
getWriteLock():
lock(mutex)
while(readers) {
wait(writerCondVar, mutex)
}
releaseWriteLock():
broadcast(readersCondVar, mutex)
unlock(mutex)
writerThread():
forever() {
getWriteLock()
write()
releaseWriteLock()
}
简单,你想怎么做就怎么做。要解决世界末日发出的信号,你必须在
抓取互斥后和等待前再次检查条件:
consumer() {
get_readlock();
if(array_empty()) {
release_readlock();
grab_mutex();
if(array_empty()) {
wait_on_condition();
}
release_mutex();
get_readlock();
}
process_elements();
release_readlock();
}
C++0x正在获得多线程支持,该支持包括一种称为条件变量的新类型:
class condition_variable_any
{
public:
condition_variable_any();
~condition_variable_any();
condition_variable_any(const condition_variable_any&) = delete;
condition_variable_any& operator=(const condition_variable_any&) = delete;
void notify_one();
void notify_all();
template <class Lock>
void wait(Lock& lock);
template <class Lock, class Predicate>
void wait(Lock& lock, Predicate pred);
template <class Lock, class Clock, class Duration>
cv_status
wait_until(Lock& lock,
const chrono::time_point<Clock, Duration>& abs_time);
template <class Lock, class Clock, class Duration, class Predicate>
bool
wait_until(Lock& lock,
const chrono::time_point<Clock, Duration>& abs_time,
Predicate pred);
template <class Lock, class Rep, class Period>
cv_status
wait_for(Lock& lock,
const chrono::duration<Rep, Period>& rel_time);
template <class Lock, class Rep, class Period, class Predicate>
bool
wait_for(Lock& lock,
const chrono::duration<Rep, Period>& rel_time,
Predicate pred);
};
类条件\u变量\u任何
{
公众:
条件变量任意();
~condition_variable_any();
条件变量任意(常数条件变量任意&)=删除;
条件变量和运算符=(常量条件变量和运算符)=删除;
无效通知一个();
无效通知所有人();
模板
无效等待(锁定和锁定);
模板
无效等待(锁定&锁定,谓词pred);
模板
cv_状态
等待(锁定和锁定),
常数计时:时间点和绝对时间);
模板
布尔
等待(锁定和锁定),
常数计时:时间点和绝对时间,
谓词pred);
模板
cv_状态
等待(锁定和锁定),
常数时间:持续时间和相对时间);
模板
布尔
等待(锁定和锁定),
常数时间::持续时间和相对时间,
谓词pred);
};
这里有一个关于如何实现条件变量的说明:
但是在这个链接中,它被命名为gen_cond_var。条件变量的神奇之处在于,它将等待任何具有lock()和unlock()成员的对象。一旦有了条件变量,那么您所需要的就是一个rwlock。上面的链接还引入了共享互斥锁和共享锁,并显示了执行您想要的操作的示例代码:
std::tr2::shared_mutex mut;
std::gen_cond_var cv;
void wait_in_shared_ownership_mode()
{
std::tr2::shared_lock<std::tr2::shared_mutex> shared_lk(mut);
// mut is now shared-locked
// ...
while (not_ready_to_proceed())
cv.wait(shared_lk); // shared-lock released while waiting
// mut is now shared-locked
// ...
} // mut is now unlocked
void wait_in_unique_ownership_mode()
{
std::unique_lock<std::tr2::shared_mutex> lk(mut);
// mut is now unique-locked
// ...
while (not_ready_to_proceed())
cv.wait(lk); // unique-lock released while waiting
// mut is now unique-locked
// ...
} // mut is now unlocked
std::tr2::shared_mutex mut;
标准::发电条件变量cv;
在共享所有权模式()下无效等待
{
std::tr2::共享锁共享锁(mut);
//mut现在被共享锁定
// ...
while(未准备好继续)
cv.wait(shared_lk);//在等待时释放共享锁
//mut现在被共享锁定
// ...
}//mut现在已解锁
在唯一所有权模式()下无效等待
{
std::唯一锁lk(mut);
//mut现在是唯一锁定的
// ...
while(未准备好继续)
cv.wait(lk);//等待时释放的唯一锁
//mut现在是唯一锁定的
// ...
}//mut现在已解锁
上面的文档有些过时。这里有一个更为最新的共享互斥/共享锁实现和描述:
这一切都是在POSIX p螺纹的基础上实现的。我希望把共享的锁东西放入C++技术报告(Tr2)中。,但这当然不能保证。
在互斥体和condvar之上实现了几个。选择任意一个并添加一些condvar以满足您的自定义需要。我有与您相同的要求
以下是我的解决方案:
包装pthread\u rwlock\t
用法
制作人
消费者
std::唯一锁定锁定(lock);
当(!准备就绪){
cond.wait(lock_u3;,[{return ready;});
}
...
就绪=错误;
警告,此解决方案可能会导致一个大问题:在第一次释放\u readlock和第一次抓取\u mutex之间,消费者可以将手交给生产商,而此生产商可以填充阵列并向任何人发送信号。如果发生这种情况,当消费者实际执行等待\u on \u条件时,它可能会被阻止,等待生产商已经发送的信号cer。它很简单,并且做了我想要的事情!我想要一种通过condvar重用pthread rBlock的方法,但我可能错了:-)
std::tr2::shared_mutex mut;
std::gen_cond_var cv;
void wait_in_shared_ownership_mode()
{
std::tr2::shared_lock<std::tr2::shared_mutex> shared_lk(mut);
// mut is now shared-locked
// ...
while (not_ready_to_proceed())
cv.wait(shared_lk); // shared-lock released while waiting
// mut is now shared-locked
// ...
} // mut is now unlocked
void wait_in_unique_ownership_mode()
{
std::unique_lock<std::tr2::shared_mutex> lk(mut);
// mut is now unique-locked
// ...
while (not_ready_to_proceed())
cv.wait(lk); // unique-lock released while waiting
// mut is now unique-locked
// ...
} // mut is now unlocked
class rwlock
{
public:
rwlock()
{
pthread_rwlock_init(&_lock, nullptr);
}
~rwlock()
{
pthread_rwlock_destroy(&_lock);
}
void read_lock()
{
pthread_rwlock_rdlock(&_lock);
}
void write_lock()
{
pthread_rwlock_wrlock(&_lock);
}
bool try_read_lock()
{
return pthread_rwlock_tryrdlock(&_lock) == 0;
}
bool try_write_lock()
{
return pthread_rwlock_trywrlock(&_lock) == 0;
}
void lock()
{
read_lock();
}
void try_lock()
{
try_read_lock();
}
void unlock()
{
pthread_rwlock_unlock(&_lock);
}
private:
pthread_rwlock_t _lock;
};
rwlock lock;
std::condition_variable_any cond;
bool ready = false;
lock.write_lock();
...
if (!ready) {
ready = true;
cond.notify_all();
}
lock.unlock();
std::unique_lock<rwlock> lock_(lock);
while (!ready) {
cond.wait(lock_, []{ return ready; });
}
...
ready = false;