tau*_*ran 124 c++ multithreading synchronization boost-thread c++11
是不是C++ 0x没有信号量?Stack Overflow上已经有一些关于信号量使用的问题.我一直使用它们(posix信号量)让线程等待另一个线程中的某个事件:
void thread0(...)
{
  doSomething0();
  event1.wait();
  ...
}
void thread1(...)
{
  doSomething1();
  event1.post();
  ...
}
如果我用互斥量做到这一点:
void thread0(...)
{
  doSomething0();
  event1.lock(); event1.unlock();
  ...
}
void thread1(...)
{
  event1.lock();
  doSomethingth1();
  event1.unlock();
  ...
}
问题:它很难看并且不能保证thread1首先锁定互斥锁(假设同一个线程应该锁定和解锁互斥锁,你也无法在thread0和thread1启动之前锁定event1).
因此,由于boost也没有信号量,实现上述目标的最简单方法是什么?
Max*_*kin 171
您可以使用互斥锁和条件变量轻松构建一个:
#include <mutex>
#include <condition_variable>
class semaphore
{
private:
    std::mutex mutex_;
    std::condition_variable condition_;
    unsigned long count_ = 0; // Initialized as locked.
public:
    void notify() {
        std::lock_guard<decltype(mutex_)> lock(mutex_);
        ++count_;
        condition_.notify_one();
    }
    void wait() {
        std::unique_lock<decltype(mutex_)> lock(mutex_);
        while(!count_) // Handle spurious wake-ups.
            condition_.wait(lock);
        --count_;
    }
    bool try_wait() {
        std::lock_guard<decltype(mutex_)> lock(mutex_);
        if(count_) {
            --count_;
            return true;
        }
        return false;
    }
};
Tsu*_*oka 101
根据Maxim Yegorushkin的回答,我尝试用C++ 11风格制作示例.
#include <mutex>
#include <condition_variable>
class Semaphore {
public:
    Semaphore (int count_ = 0)
        : count(count_) {}
    inline void notify()
    {
        std::unique_lock<std::mutex> lock(mtx);
        count++;
        cv.notify_one();
    }
    inline void wait()
    {
        std::unique_lock<std::mutex> lock(mtx);
        while(count == 0){
            cv.wait(lock);
        }
        count--;
    }
private:
    std::mutex mtx;
    std::condition_variable cv;
    int count;
};
Dav*_*vid 38
我决定像我一样能写出最强大的/通用的C++ 11旗语我可以,在标准样式(注意using semaphore = ...,你通常只会使用的名称semaphore类似的正常使用string没有basic_string):
template <typename Mutex, typename CondVar>
class basic_semaphore {
public:
    using native_handle_type = typename CondVar::native_handle_type;
    explicit basic_semaphore(size_t count = 0);
    basic_semaphore(const basic_semaphore&) = delete;
    basic_semaphore(basic_semaphore&&) = delete;
    basic_semaphore& operator=(const basic_semaphore&) = delete;
    basic_semaphore& operator=(basic_semaphore&&) = delete;
    void notify();
    void wait();
    bool try_wait();
    template<class Rep, class Period>
    bool wait_for(const std::chrono::duration<Rep, Period>& d);
    template<class Clock, class Duration>
    bool wait_until(const std::chrono::time_point<Clock, Duration>& t);
    native_handle_type native_handle();
private:
    Mutex   mMutex;
    CondVar mCv;
    size_t  mCount;
};
using semaphore = basic_semaphore<std::mutex, std::condition_variable>;
template <typename Mutex, typename CondVar>
basic_semaphore<Mutex, CondVar>::basic_semaphore(size_t count)
    : mCount{count}
{}
template <typename Mutex, typename CondVar>
void basic_semaphore<Mutex, CondVar>::notify() {
    std::lock_guard<Mutex> lock{mMutex};
    ++mCount;
    mCv.notify_one();
}
template <typename Mutex, typename CondVar>
void basic_semaphore<Mutex, CondVar>::wait() {
    std::unique_lock<Mutex> lock{mMutex};
    mCv.wait(lock, [&]{ return mCount > 0; });
    --mCount;
}
template <typename Mutex, typename CondVar>
bool basic_semaphore<Mutex, CondVar>::try_wait() {
    std::lock_guard<Mutex> lock{mMutex};
    if (mCount > 0) {
        --mCount;
        return true;
    }
    return false;
}
template <typename Mutex, typename CondVar>
template<class Rep, class Period>
bool basic_semaphore<Mutex, CondVar>::wait_for(const std::chrono::duration<Rep, Period>& d) {
    std::unique_lock<Mutex> lock{mMutex};
    auto finished = mCv.wait_for(lock, d, [&]{ return mCount > 0; });
    if (finished)
        --mCount;
    return finished;
}
template <typename Mutex, typename CondVar>
template<class Clock, class Duration>
bool basic_semaphore<Mutex, CondVar>::wait_until(const std::chrono::time_point<Clock, Duration>& t) {
    std::unique_lock<Mutex> lock{mMutex};
    auto finished = mCv.wait_until(lock, t, [&]{ return mCount > 0; });
    if (finished)
        --mCount;
    return finished;
}
template <typename Mutex, typename CondVar>
typename basic_semaphore<Mutex, CondVar>::native_handle_type basic_semaphore<Mutex, CondVar>::native_handle() {
    return mCv.native_handle();
}
小智 15
根据posix信号量,我想补充一下
class semaphore
{
    ...
    bool trywait()
    {
        boost::mutex::scoped_lock lock(mutex_);
        if(count_)
        {
            --count_;
            return true;
        }
        else
        {
            return false;
        }
    }
};
而且我更喜欢在方便的抽象级别使用同步机制,而不是总是使用更基本的运算符复制粘贴拼接在一起的版本.
ein*_*ica 11
C++20 终于有了信号量 - std::counting_semaphore<max_count>。
这些具有(至少)以下方法:
acquire() (阻塞)try_acquire() (非阻塞,立即返回)try_acquire_for() (非阻塞,需要一段时间)try_acquire_until() (非阻塞,需要一段时间才能停止尝试)release()您可以阅读这些 CppCon 2019 演示幻灯片,或观看视频。还有官方提案P0514R4,但它可能不是最新的实际 C++20。
| 归档时间: | 
 | 
| 查看次数: | 77193 次 | 
| 最近记录: |