0

我正在为 c++11 编写一个带有简单信号量实现的消费者/生产者类。但是,以下代码无法编译。如果我删除producer_consumer类和makeproducerconsumer全局函数,并将线程创建部分(std::thread t1(consumer), t2(consumer); t1.join(); t2.join();)移动到main函数中,它可以编译,但实现仍然不正确,最终会导致分段错误。如何更正代码?谢谢。

#include <iostream>
#include <thread>
#include <mutex>

class semaphore {
private:
    std::mutex m;
    std::condition_variable cond;
    unsigned long n;
public:
    semaphore(int i) : n(i) {}

    void up() {
        std::unique_lock <std::mutex> lock (m);
        ++n;
        cond.notify_one();
    }

    void down() {
        std::unique_lock <std::mutex> lock (m);
        while(!n) cond.wait(lock);
        --n;
    }
};
class producer_consumer{
private:
    semaphore full, empty;
    int i = 0;
    std::thread t1, t2;
public:
    producer_consumer(int n): full(0), empty(n), i(0){}
    void run(){
        t1 = std::thread(&producer_consumer::producer, *this); 
        t2 = std::thread(&producer_consumer::consumer, *this);
    }
    void stop(){
        t1.join();
        t2.join();
    }
    void producer (){
        while (true){
            empty.down();
            i ++;
            std::cout << "[p]" << i << std::endl;
            full.up();  
        }
    }
    void consumer (){
        while (true){
            full.down();
            i --;
            std::cout << "[c]" << i << std::endl;
            empty.up(); 
        }
    }
};

int main(){
    producer_consumer pc(5);
    pc.run();
    pc.stop();
    return 0;
}

我使用 clang++ 编译文件:

clang++ -std=c++0x -stdlib=libc++ pc.cpp ; ./a.out

错误信息:

In file included from file_name.cpp:1:
In file included from /usr/bin/../lib/c++/v1/iostream:38:
In file included from /usr/bin/../lib/c++/v1/ios:216:
In file included from /usr/bin/../lib/c++/v1/__locale:15:
In file included from /usr/bin/../lib/c++/v1/string:434:
In file included from /usr/bin/../lib/c++/v1/algorithm:591:
/usr/bin/../lib/c++/v1/type_traits:1423:12: error: call to implicitly-deleted
      copy constructor of 'typename decay<producer_consumer &>::type'
      (aka 'producer_consumer')
    return _VSTD::forward<_Tp>(__t);
           ^~~~~~~~~~~~~~~~~~~~~~~~

更新:@DanqiWang 通过更改*thisthis. 现在看来,信号量不能正常工作,最终会使程序崩溃:

./a.out
[p]1
[p]2
[p]3
[p]4
[p]5
....
[p]2
[p]3
[p]4
1
[c]3
[p[]c3]
3
[[c]3
p][2c
][p]3
[p]4
4
[c]3
[c]2
Segmentation fault: 11
4

1 回答 1

3

我对您的代码有以下建议:

  • 尽管iostream在 C++11 中成为线程安全的,但它应该被锁定以避免输出错误。
  • 使用std::atomic而不是裸int
  • 如果有段错误,转储内核,用于gdb调试它,或在此处发布堆栈跟踪。

希望这些帮助。

于 2012-08-30T05:57:27.763 回答