Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将pthread条件变量与rwlock一起使用 < >我想用一种方法来使用 pththrWLoCu条件C++中的例程> _C++_C_Posix_Pthreads_Producer Consumer - Fatal编程技术网

将pthread条件变量与rwlock一起使用 < >我想用一种方法来使用 pththrWLoCu条件C++中的例程>

将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时,多个读卡器不会阻塞。为了

我有两个问题:

第一:怎么可能?如果我们不能,为什么

第二:为什么当前的POSIX pthread没有实现这种行为

为了理解我的目的,我解释了我的用途:我有一个生产者-消费者模型来处理一个共享阵列。当数组为空时,使用者将进行cond_等待,但在读取某些元素时,使用者将进行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;