国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux基于多線程和任務隊列實現生產消費模型

這篇具有很好參考價值的文章主要介紹了Linux基于多線程和任務隊列實現生產消費模型。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

一、生產者消費者模型

二、代碼實現模型

2.1 BlockQueue.hpp

2.2 MainCP.cc

2.3 執(zhí)行結果

三、效率優(yōu)勢


一、生產者消費者模型

Linux基于多線程和任務隊列實現生產消費模型,Linux,linux

將上述圖片邏輯轉換成代碼邏輯就是,一批線程充當生產者角色,一批線程充當消費者角色,倉庫是生產者和消費者獲取的公共資源!下面我想用321原則來解釋這個模型。

既然是公共資源,那么我們就需要考慮線程安全問題!

3指的是三者之間的關系!當一個生產者向倉庫生產資源的時候,消費者不可以進入倉庫取資源!同樣,當一個生產者向倉庫放入資源的時候,其他生產者不能同時也向同一個位置放入資源,也就是說生產者要等上一個生產者走出倉庫后進入倉庫!同樣消費者與消費者也是這樣的關系!也就是說生產者與生產者互斥,生產者與消費者互斥,消費者與消費者互斥

當消費者與生產者完成自己的操作后,會提醒對方前來進行對方的操作!也就是說,生產者與消費者同步!

2指的是2中角色:生產者和消費者

1指的是存儲資源的容器(倉庫):一段特定結構的緩沖區(qū)(隊列、棧、鏈表)


二、代碼實現模型

2.1 BlockQueue.hpp

#pragma once
#include<iostream>
#include<pthread.h>
#include<queue>

template <class T>
class BlockQueue
{
public:
    static const int gmaxcap = 5;

     BlockQueue(const int maxcap = gmaxcap):_capacity(maxcap)
     {
        //初始化
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_pcond,nullptr);
        pthread_cond_init(&_ccond,nullptr);
     }

    void push(const T& in)
    {
        //加鎖互斥
        pthread_mutex_lock(&_mutex);

        //細節(jié):為什么這里用while循環(huán)判斷? 
        //-->有一種可能性,當生產者很多而消費者只有一個,第一次條件滿足進入阻塞后,消費者處理了 
        // 一個任務
        //這樣就會同時喚醒一批生產者,如果只是if,他們不會再次判斷而是直接“同時!”進行后面push的 
        //邏輯!這樣不是線程安全的

        while(is_full())
        {
            pthread_cond_wait(&_pcond,&_mutex);
        }
        //進行到這表示一定有空余空間存數據
        _q.push(in);

        //喚醒消費者
        pthread_cond_signal(&_ccond);
        pthread_mutex_unlock(&_mutex);
    }

    void pop(T* out)
    {
        pthread_mutex_lock(&_mutex);
        
        //和上面邏輯一樣
        while(is_empty())
        {
            pthread_cond_wait(&_ccond,&_mutex);
        }
        //到這表示一定有數據
        *out = _q.front();
        _q.pop();
        //喚醒生產者
        pthread_cond_signal(&_pcond);
        pthread_mutex_unlock(&_mutex);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_pcond);
        pthread_cond_destroy(&_ccond);
    }
private:
    bool is_empty()
    {
        return _q.empty();
    }
    bool is_full()
    {
        return _q.size() == _capacity;
    }
private:
    std::queue<T> _q; //存儲任務隊列
    int _capacity;
    pthread_mutex_t _mutex; //一把鎖 -> 3互斥原則
    pthread_cond_t _pcond; //生產者條件變量
    pthread_cond_t _ccond; //消費者條件變量
};


2.2 MainCP.cc

#include "BlockQueue.hpp"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <functional>

// 任務對象
class Task
{
public:
    //==typedef
    using func_t = std::function<double(int, int, char)>; 

    Task() {}

    Task(func_t callback, int x = 0, int y = 0, char op = '+') : _x(x), _y(y), _op(op), _callback(callback)
    {
    }
    // 仿函數
    std::string operator()()
    {
        double ret = _callback(_x, _y, _op);
        char buffer[64];
        snprintf(buffer, sizeof buffer, "%d %c %d = %lf", _x, _op, _y, ret);
        return buffer;
    }

private:
    int _x;
    int _y;
    char _op;
    func_t _callback; // 回調函數
};

//處理數據函數
double calculator(int x, int y, char op)
{
    double ret = 0.0;
    switch (op)
    {
    case '+':
        ret = x + y;
        break;
    case '-':
        ret = x - y;
        break;
    case '*':
        ret = x * y;
        break;
    case '/':
        if (y == 0)
            ret = 0;
        else
            ret = (double)x / y;
        break;
    case '%':
        if (y == 0)
            ret = 0;
        else
            ret = x % y;
        break;
    default:
        break;
    }
    return ret;
}

// 生產者任務
void *producer(void *args)
{
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    while (true)
    {
        // 1.獲取數據
        const char *str = "+-*/%";
        int x = rand() % 10 + 1;
        int y = rand() % 5 + 1;
        char op = str[rand() % 5];

        // 2.構建任務對象&傳送對于的處理方法
        Task t(calculator, x, y, op);

        // 3.存入隊列
        bq->push(t);
        std::cout << "生產任務: " << x << " " << op << " " << y << " = ?" << std::endl;
        sleep(1);
    }
}

// 消費者任務
void *consumer(void *args)
{
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    while (true)
    {
        Task t;

        // 1.獲取任務
        bq->pop(&t);

        // 2.執(zhí)行仿函數
        std::cout << "消費任務: " << t() << std::endl;
    }
}

int main()
{
    srand((unsigned long)time(nullptr) ^ getpid());

    pthread_t c, p;

    BlockQueue<Task> *bq = new BlockQueue<Task>();
    pthread_create(&c, nullptr, consumer, bq);
    pthread_create(&p, nullptr, producer, bq);

    pthread_join(c, nullptr);
    pthread_join(p, nullptr);
    return 0;
}

2.3 執(zhí)行結果

Linux基于多線程和任務隊列實現生產消費模型,Linux,linux


三、效率優(yōu)勢

上面的是單個線程,可以拓展到多生產者多消費者!但是我們疑惑的是這個模型在訪問資源的時候,都是互斥的!他們只有一個能進入到臨界區(qū),這樣怎么是高效的?原來這個模型的高效不是在訪問臨界資源,而是對于每個線程可以獨立的準備數據!我們上述實現的數據來源以及數據處理是簡單的,但是后面數據可能來源于網絡或者磁盤文件,這個過程每個線程都可以同時在線獲取或者處理!這個過程如果串行是低效率的,但是多線程可以大大提高IO效率!這就是生產者消費者模型高效的原因!它可以將IO數據分散給多個線程并行處理,極大地提高了效率!文章來源地址http://www.zghlxwxcb.cn/news/detail-701561.html

到了這里,關于Linux基于多線程和任務隊列實現生產消費模型的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【Linux】基于環(huán)形隊列的生產者消費者模型的實現

    【Linux】基于環(huán)形隊列的生產者消費者模型的實現

    文章目錄 前言 一、基于環(huán)形隊列的生產者消費者模型的實現 上一篇文章我們講了信號量的幾個接口和基于環(huán)形隊列的生產者消費者模型,下面我們就快速來實現。 首先我們創(chuàng)建三個文件,分別是makefile,RingQueue.hpp,以及main.cc。我們先簡單搭建一下環(huán)形隊列的框架: 首先我們

    2024年02月11日
    瀏覽(26)
  • Linux之【多線程】生產者與消費者模型&BlockQueue(阻塞隊列)

    Linux之【多線程】生產者與消費者模型&BlockQueue(阻塞隊列)

    舉個例子:學生要買東西,一般情況下都會直接聯系廠商,因為買的商品不多,對于供貨商來說交易成本太高,所以有了交易場所超市這個媒介的存在。目的就是為了集中需求,分發(fā)產品。 消費者與生產者之間通過了超市進行交易。當生產者不需要的時候,廠商可以繼續(xù)生產

    2024年02月02日
    瀏覽(29)
  • 【linux】POSIX信號量+基于環(huán)形隊列的生產消費模型

    【linux】POSIX信號量+基于環(huán)形隊列的生產消費模型

    喜歡的點贊,收藏,關注一下把! 上篇文章最后我們基于BlockQueue生產者消費者模型寫了代碼,測試什么的都通過了。最后我們說代碼還有一些不足的地方,由這些不足從而引入了我們接下來要學的信號量! 我們在看一看不足的地方 1.一個線程,在操作臨界資源的時候,必須

    2024年02月01日
    瀏覽(25)
  • 【Linux系統(tǒng)編程二十九】基于信號量的環(huán)形隊列生產消費模型

    【Linux系統(tǒng)編程二十九】基于信號量的環(huán)形隊列生產消費模型

    當共享資源被當成整體使用時,則共享資源的數量要么是1,要么是0。 當被訪問使用時,共享資源的數量就為0,當沒有被使用時,數量就為1。 共享資源是可以被分成多份來使用的,只不過不同的線程訪問的是該共享資源的不同的區(qū)域,它是允許多個線程并發(fā)訪問的,只不過

    2024年01月22日
    瀏覽(28)
  • 【linux】線程同步+基于BlockingQueue的生產者消費者模型

    【linux】線程同步+基于BlockingQueue的生產者消費者模型

    喜歡的點贊,收藏,關注一下把! 在線程互斥寫了一份搶票的代碼,我們發(fā)現雖然加鎖解決了搶到負數票的問題,但是一直都是一個線程在搶票,它錯了嗎,它沒錯但是不合理。那我們應該如何安全合理的搶票呢? 講個小故事。 假設學校有一個VIP學霸自習室,這個自習室有

    2024年02月03日
    瀏覽(24)
  • 【Linux】POSIX信號量 | 基于環(huán)形隊列的生產者消費者模型

    【Linux】POSIX信號量 | 基于環(huán)形隊列的生產者消費者模型

    ??? 作者:@阿亮joy. ?? 專欄: 《學會Linux》 ?? 座右銘:每個優(yōu)秀的人都有一段沉默的時光,那段時光是付出了很多努力卻得不到結果的日子,我們把它叫做扎根 POSIX 信號量和 SystemV 信號量作用相同,都是用于同步操作,達到無沖突的訪問共享資源目的。 但 POSIX 可以用于

    2023年04月08日
    瀏覽(43)
  • Python多線程Thread——生產者消費者模型 python隊列與多線程——生產者消費者模型

    下面面向對象的角度看線程 那么你可以試試看能不能用面向對象的方法實現生產者消費者模型吧。

    2024年02月09日
    瀏覽(35)
  • 多線程(初階七:阻塞隊列和生產者消費者模型)

    多線程(初階七:阻塞隊列和生產者消費者模型)

    目錄 一、阻塞隊列的簡單介紹 二、生產者消費者模型 1、舉個栗子: 2、引入生產者消費者模型的意義: (1)解耦合 (2)削峰填谷 三、模擬實現阻塞隊列 1、阻塞隊列的簡單介紹 2、實現阻塞隊列 (1)實現普通隊列 (2)加上線程安全 (3)加上阻塞功能 3、運用阻塞隊列

    2024年02月05日
    瀏覽(20)
  • 【Linux】多線程 --- 線程同步與互斥+生產消費模型

    【Linux】多線程 --- 線程同步與互斥+生產消費模型

    人生總是那么痛苦嗎?還是只有小時候是這樣? —總是如此 1. 假設現在有一份共享資源tickets,如果我們想讓多個線程都對這個資源進行操作,也就是tickets- -的操作,但下面兩份代碼分別出現了不同的結果,上面代碼并沒有出現問題,而下面代碼卻出現了票為負數的情況,這

    2024年02月06日
    瀏覽(22)
  • [計網底層小探索]:實現并部署多線程并發(fā)Tcp服務器框架(基于生產者消費者模型的線程池結構)

    [計網底層小探索]:實現并部署多線程并發(fā)Tcp服務器框架(基于生產者消費者模型的線程池結構)

    網絡層與傳輸層 內置于操作系統(tǒng)的內核中 ,網絡層一般使用 ip 協議,傳輸層常用協議為 Tcp 協議和 Udp 協議, Tcp 協議和 Udp 協議擁有各自的特點和應用場景: sockaddr_in 結構體用于存儲網絡通信主機進程的 ip 和端口號等信息 小項目的完整文件的gittee鏈接 Tcp 服務器架構: 序列反序列

    2024年02月22日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包