多線程間的互斥(上)


值得思考的問題:

多個線程除了在時序上可能產生相互依賴,在其他方面是否也可能產生相互依賴呢?

生產消費者問題:
-有n個生產者同時制造產品,並把產品存入倉庫中

-有m個消費者同時需要從倉庫中取出產品

-規則:

當倉庫未滿,任意生產者可以存入產品

當倉庫未空,任意消費者可以取出產品

編程實驗:生產消費者問題

 

#include <QCoreApplication> #include <QThread> #include <QDebug>

static QString q_store;    //通過全局變量來模擬唯一的倉庫

class Producer : public QThread { protected: void run() { int count = 0; while(true) { //每次產生的數字在0-10之間,模擬了生產者將生產好的產品(一個數字)放入到倉庫中(一個字符串類的對象)
          q_store.append(QString::number((count++) % 10)); qDebug() << objectName() << " :" + q_store; //用字符串中字符表示當前倉庫中的商品
          msleep(1); } } }; class Customer : public QThread { protected: void run() { while(true) { if(q_store != " ") { q_store.remove(0,1); //刪除字符串中的第一個字符,表示取出一個商品
                qDebug() << objectName() << " : " + q_store; } msleep(1); } } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() << "main begin()" ; Producer p; Customer c; p.setObjectName("Producer"); c.setObjectName("Customer"); p.start(); c.start(); qDebug() << "main end()"; return a.exec(); }

 

在程序中,如果只分析生產者是沒有問題的,同樣如果只分析消費者也是沒有問題的。出現問題的原因就是生產者和消費者是並行執行的,並且共享一個倉庫。兩個線程之間沒有任何的限制或約束。考慮一種情況,生產者在向倉庫中放入產品的同時,消費者從倉庫中取產品。相當於對共享資源同時讀寫,這肯定是不對的,也是不行的。

 

 

 

 

 

 

 臨界資源(Critical Resource)

-每次只允許一個線程進行訪問(讀/寫)的資源

-線程間的互斥(競爭)

-多個線程在同一時刻都需要訪問臨界資源

QMutex類是一把線程鎖,保證線程間的互斥

-利用線程鎖能夠保證臨界資源的安全性

QMutex中的關鍵成員函數

-void lock()

  當鎖空閑時,獲取鎖並繼續執行

  當鎖被獲取,阻塞並等待鎖釋放

-void unlock()

  釋放鎖(同一把鎖的獲取和釋放必須在同一線程中成對出現)

QMutex使用示例

QMutex mutex;

mutex.lock();

//do something with critical resource

mutex.unlock();

注意:如果mutex在調用unlock()時處於空閑狀態(即在調用lock函數之前就調用了unlock),那么程序的行為是未定的。所謂未定義就是什么時候產生bug,是不知道的。

解決生產者消費者問題:

 

#include <QCoreApplication> #include <QThread> #include <QDebug> #include <QMutex>

static QString q_store;    //通過全局變量來模擬唯一的倉庫
static QMutex mutex; class Producer : public QThread { protected: void run() { int count = 0; while(true) { mutex.lock(); //每次產生的數字在0-10之間,模擬了生產者將生產好的產品(一個數字)放入到倉庫中(一個字符串類的對象)
          q_store.append(QString::number((count++) % 10)); qDebug() << objectName() << " :" + q_store; //用字符串中字符表示當前倉庫中的商品
          msleep(1); mutex.unlock(); } } }; class Customer : public QThread { protected: void run() { while(true) { mutex.lock(); if(q_store != " ") { q_store.remove(0,1); //刪除字符串中的第一個字符,表示取出一個商品
                qDebug() << objectName() << " : " + q_store; } msleep(1);  mutex.unlock(); } } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() << "main begin()" ; Producer p; Customer c; p.setObjectName("Producer"); c.setObjectName("Customer"); p.start(); c.start(); qDebug() << "main end()"; return a.exec(); }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM