C++多线程的实现

在C++环境下面, 要实现多线程并发, 提升性能, 并不是一件很容易的事情。 难点不是如何划分出多个线程, 而是如何确认哪些内存是线程间公用的, 需要避免冲突, 另一个方面, 如何做到线程间同步。

线程私有数据

在一个线程里面, 线程ID和堆栈上的数据, 以及信号集等是线程私有的, 我们还可以通过一些函数指定线程的私有数据, 比如pthread_setspecific。

线程之间通信

线程之间的通信方式, 常见的有2种:信号通知以及管道通知。

信号通知

通常会有信号的产生端和消费端, 信号的产生端通常是有一个队列, 每当有新的信号产生, 就加入到信号里面, 消费端通常是一个后台线程, 每当收到通知, 信号队列非空, 就会暂时锁定队列, 并且将队列的内容swap到新的队列, 解锁之后, 就可以逐个遍历,处理每个信号。

信号产生端:

class Producer {
    std::list<Item*>  queue;
    void AddItem(Item* item) {
           pthread_lock(&mutex);
           queue.push_back(item);
           pthread_cond_signal(&cond);
           pthread_unloc(&mutex);
    }
}

信号消费端:

class Consumer {
public:
    void process() {
            pthread_mutex_lock();
            while (1) {
                  std::list<Item*>  queuetmp;
                   if (!queue.empty()) {
                         queuetmp.swap(queue);
                   }
                   pthread_mutex_unlock();
                   while (!queuetmp.empty()) {
                             Item* item = queuetmp.front();
                             queuetmp.pop_front();
                             handler(item);
                   }
                   pthread_mutex_lock();
                   pthread_cond_wait(&cond);
            }
    }
}
管道通知

管道是使用非常广泛的一种消息通知机制, 可以用于线程间或者进程间通信。pipe函数会产生2个文件描述符,通过pipe函数创建的这两个文件描述符 fd[0] 和 fd[1] 分别构成管道的两端,往 fd[1] 写入的数据可以从 fd[0] 读出。并且 fd[1] 一端只能进行写操作,fd[0] 一端只能进行读操作,不能反过来使用。要实现双向数据传输,可以使用两个管道。

信号产生端:

class Producer {
    std::list<Item*>  queue;
    int wrfd;
    void AddItem(Item* item) {
           pthread_lock(&mutex);
           queue.push_back(item);
           pthread_unloc(&mutex);
 
          // write message to pipe to notify consumer part 
          write(wrfd, data, size);
    }
}

信号消费端:

class Consumer {

private:
     int rdfd; 
public:
    void process() {
            // pipe data reader part, using read blocking-mode,
            // only when producer part has data written, it will go to
            // the while range
            while (read(rdfd, buf, size) > 0) {
                  pthread_mutex_lock();
                  std::list<Item*>  queuetmp;
                   if (!queue.empty()) {
                         queuetmp.swap(queue);
                   }
                   pthread_mutex_unlock();
                   while (!queuetmp.empty()) {
                             Item* item = queuetmp.front();
                             queuetmp.pop_front();
                             handler(item);
                   }
            }
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值