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);
                   }
            }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章