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

【Linux】生產(chǎn)者消費者模型(阻塞隊列與環(huán)形隊列)和POSIX信號量

這篇具有很好參考價值的文章主要介紹了【Linux】生產(chǎn)者消費者模型(阻塞隊列與環(huán)形隊列)和POSIX信號量。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、生產(chǎn)者消費者模型

我們這里舉一個例子,來解釋生產(chǎn)者消費者模型,我們學(xué)生–消費者,供應(yīng)商–生產(chǎn)者,超市–交易場所,我們買東西只需要關(guān)系售貨架子上是否有商品即可,沒有了商品,超市從供應(yīng)商進行供貨。供應(yīng)商和供應(yīng)商不能同時向一個貨架進行供貨,所以生產(chǎn)者之間是互斥的關(guān)系,非消費者和消費不能同時從同一個貨架拿商品,所以消費者與消費者之間是互斥的關(guān)系,而消費者需要等生產(chǎn)者將商品放到貨架之后才能拿取商品,所以生產(chǎn)者和消費者之間是互斥和同步的關(guān)系。

生產(chǎn)消費模型:

生產(chǎn)者和生產(chǎn)者之間:互斥關(guān)系

消費者和消費者之間:互斥關(guān)系

生產(chǎn)者和消費者之間:互斥&&同步

總結(jié):“321”原則:

3種關(guān)系:生產(chǎn)者和生產(chǎn)者(互斥),消費者和消費者(互斥),生產(chǎn)者和消費者

互斥保證共享資源的安全性]同步)–產(chǎn)品(數(shù)據(jù))

種角色:生產(chǎn)者線程,消費者線程

1個交易場所:(一段特定結(jié)構(gòu)的緩沖區(qū)

只要我們想寫生產(chǎn)消費模型,我們本質(zhì)工作其實就是維護321原則!

挖掘特點:

1.生產(chǎn)線程和消費線程進行解耦

2支持生產(chǎn)和消費的一段時間的忙閑不均的問題

3.提高效率

生產(chǎn)者消費者模式就是通過一個容器來解決生產(chǎn)者和消費者的強耦合問題。生產(chǎn)者和消費者彼此之間不直接通訊,而通過阻塞隊列來進行通訊,所以生產(chǎn)者生產(chǎn)完數(shù)據(jù)之后不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產(chǎn)者要數(shù)據(jù),而是直接從阻塞隊列里取,阻塞隊列就相當(dāng)于一個緩沖區(qū),平衡了生產(chǎn)者和消費者的處理能力。這個阻塞隊列就是用來給生產(chǎn)者和消費者解耦的。

生產(chǎn)者消費者模型優(yōu)點

解耦

支持并發(fā)

支持忙閑不均

【Linux】生產(chǎn)者消費者模型(阻塞隊列與環(huán)形隊列)和POSIX信號量,Linux系統(tǒng)編程,linux,生產(chǎn)者消費者模型,阻塞隊列,環(huán)形隊列,POSIX信號量,多線程

二、基于BlockingQueue的生產(chǎn)者消費者模型

BlockingQueue

在多線程編程中阻塞隊列(Blocking Queue)是一種常用于實現(xiàn)生產(chǎn)者和消費者模型的數(shù)據(jù)結(jié)構(gòu)。其與普通的隊列區(qū)別在于,當(dāng)隊列為空時,從隊列獲取元素的操作將會被阻塞,直到隊列中被放入了元素;當(dāng)隊列滿時,往隊列里存放元素的操作也會被阻塞,直到有元素被從隊列中取出(以上的操作都是基于不同的線程來說的,線程在對阻塞隊列進程操作時會被阻塞)

【Linux】生產(chǎn)者消費者模型(阻塞隊列與環(huán)形隊列)和POSIX信號量,Linux系統(tǒng)編程,linux,生產(chǎn)者消費者模型,阻塞隊列,環(huán)形隊列,POSIX信號量,多線程

1.BlockQueue.hpp

#pragma once

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

using namespace std;
const int gnum = 5;

template <class T>
class BlockQueue
{
public:
    BlockQueue(const int& maxcap = gnum)
        : _maxcap(maxcap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_pcond, nullptr);
        pthread_cond_init(&_ccond, nullptr);
    }

    void push(const T &in) // 輸出型參數(shù):*, // 輸入輸出型:&
    {
        pthread_mutex_lock(&_mutex);
        // 1. 判斷
        // 細(xì)節(jié)2: 充當(dāng)條件判斷的語法必須是while,不能用if
        while (is_full())
        {
            // 細(xì)節(jié)1:pthread_cond_wait這個函數(shù)的第二個參數(shù),必須是我們正在使用的互斥鎖!
            // a. pthread_cond_wait: 該函數(shù)調(diào)用的時候,會以原子性的方式,將鎖釋放,并將自己掛起
            // b. pthread_cond_wait: 該函數(shù)在被喚醒返回的時候,會自動的重新獲取你傳入的鎖
            pthread_cond_wait(&_pcond, &_mutex);
        }

        // 2. 走到這里一定是沒有滿
        _q.push(in);

        // 3. 絕對能保證,阻塞隊列里面一定有數(shù)據(jù)
        // 細(xì)節(jié)3:pthread_cond_signal:這個函數(shù),可以放在臨界區(qū)內(nèi)部,也可以放在外部
        
        pthread_cond_signal(&_ccond);
        pthread_mutex_unlock(&_mutex);
    }

    void pop(T *out)
    {
        pthread_mutex_lock(&_mutex);
        // 1. 判斷
        while (is_empty())
        {
            pthread_cond_wait(&_ccond, &_mutex);
        }

        // 2. 走到這里我們能保證,一定不為空
        *out = _q.front();
        _q.pop();

        // 3. 絕對能保證,阻塞隊列里面,至少有一個空的位置!
        pthread_cond_signal(&_pcond);
        pthread_mutex_unlock(&_mutex);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_pcond);
        pthread_cond_destroy(&_ccond);
    }

private:
    bool is_full()
    {
        return _q.size() == _maxcap;
    }

    bool is_empty()
    {
        return _q.empty();
    }

private:
    queue<T> _q;
    int _maxcap; // 隊列中元素的上限
    pthread_mutex_t _mutex;
    pthread_cond_t _pcond; // 生產(chǎn)者對應(yīng)的條件變量
    pthread_cond_t _ccond; // 消費者對應(yīng)的條件變量
};

2.Task.hpp

#pragma once

#include <iostream>
#include <string>
#include <functional>

class CalTask
{
public:
    typedef std::function<int(int, int, char)> func_t;
    // using func_t = std::function<int(int, int, char)>;

public:
    CalTask()
    {
    }
    CalTask(int x, int y, char op, func_t func)
        : _x(x), _y(y), _op(op), _callback(func)
    {
    }

    std::string operator()()
    {
        int result = _callback(_x, _y, _op);
        char buffer[1024];
        snprintf(buffer, sizeof buffer, "%d %c %d = %d", _x, _op, _y, result);
        return buffer;
    }

    std::string toTaskString()
    {
        char buffer[1024];
        snprintf(buffer, sizeof buffer, "%d %c %d = ?", _x, _op, _y);
        return buffer;
    }

private:
    int _x;
    int _y;
    char _op;
    func_t _callback;
};

const std::string oper = "+-*/%";

int calculate(int x, int y, char op)
{
    int result = 0;
    switch (op)
    {
    case '+':
        result = x + y;
        break;
    case '-':
        result = x - y;
        break;
    case '*':
        result = x * y;
        break;
    case '/':
    {
        if (y == 0)
        {
            std::cerr << "div zero error" << std::endl;
            return -1;
        }
        else
            result = x / y;
    }
    break;
    case '%':
    {
        if (y == 0)
        {
            std::cerr << "mod zero error" << std::endl;
            return -1;
        }
        else
            result = x % y;
    }
    break;
    default:
        std::cerr << "請輸入正確的操作符" << std::endl;
        break;
    }

    return result;
}

class SaveTask
{
public:
    using func_t = function<void(const std::string &)>;

public:
    SaveTask()
    {
    }
    SaveTask(const std::string &message, func_t func)
        : _message(message), _func(func)
    {
    }

    void operator()()
    {
        _func(_message);
    }

    ~SaveTask()
    {
    }

private:
    std::string _message;
    func_t _func;
};

void Save(const std::string &message)
{
    const std::string target = "./log.txt";
    FILE *fp = fopen(target.c_str(), "a+");
    if (fp == nullptr)
    {
        perror("fopen error");
        return;
    }
    fputs(message.c_str(), fp);
    fputs("\n", fp);

    fclose(fp);
}

3.main.cc

#include "BlockQueue.hpp"
#include "Task.hpp"

#include <ctime>
#include <unistd.h>
#include <sys/types.h>

// C:計算
// S: 存儲
template <class C, class S>
class BlockQueues
{
public:
    BlockQueue<C> *_cbq;
    BlockQueue<S> *_sbq;
};

void *productor(void *args)
{
    BlockQueue<CalTask> *bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_cbq;

    while (true)
    {
        int x = rand() % 10 + 1;
        int y = rand() % 5;
        char op = oper[rand() % 5];

        CalTask t(x, y, op, calculate);
        bq->push(t);

        std::cout << "productor thread 生產(chǎn)計算任務(wù): " << t.toTaskString() << std::endl;

        sleep(1);
    }

    return nullptr;
}

void *consumer(void *args)
{
    BlockQueue<CalTask> *bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_cbq;
    BlockQueue<SaveTask> *save_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_sbq;

    while (true)
    {
        CalTask t;
        bq->pop(&t);
        std::string result = t();

        std::cout << "cal thread,完成計算任務(wù): " << result << " ... done" << std::endl;

        SaveTask st(result, Save);
        save_bq->push(st);
        cout << "cal thread,推送存儲任務(wù)完成..." << std::endl;

        sleep(1);
    }
    return nullptr;
}

void *saver(void *args)
{
    BlockQueue<SaveTask> *save_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_sbq;

    while (true)
    {
        SaveTask st;
        save_bq->pop(&st);
        st();
        std::cout << "save thread,保存任務(wù)完成..." << std::endl;
        // sleep(1);
    }

    return nullptr;
}

int main()
{
    BlockQueues<CalTask, SaveTask> bqs;
    bqs._cbq = new BlockQueue<CalTask>();
    bqs._sbq = new BlockQueue<SaveTask>();

    pthread_t p, c, s;
    pthread_create(&p, nullptr, productor, &bqs);
    pthread_create(&c, nullptr, consumer, &bqs);
    pthread_create(&s, nullptr, saver, &bqs);

    pthread_join(p, nullptr);
    pthread_join(c, nullptr);
    pthread_join(s, nullptr);

    delete bqs._cbq;
    delete bqs._sbq;

    return 0;
}

你創(chuàng)建多線程生產(chǎn)和消費的意義是什么??2.生產(chǎn)消費模型高效在哪里??

可以在生產(chǎn)之前,和消費之后,讓線程并行執(zhí)行

生產(chǎn)者而言,向blockqueue里面放置任務(wù)

他的任務(wù)從哪里來的呢?它獲取任務(wù)和構(gòu)建任務(wù)要不要花時間?

消費者而言,從blockqueue里面拿取任務(wù)

對于消費者,難道他把任務(wù)從任務(wù)隊列中拿出來就完了嗎??消費者拿到任務(wù)之后,后續(xù)還有沒有任務(wù)??

三、POSIX信號量

先發(fā)現(xiàn)我們之前寫的代碼的不足的地方

pthread_mutex_lock(&_mutex);
while (is_full())
{
    pthread_cond_wait(&_pcond, &_mutex);
}
_q.push(in);
pthread_cond_signal(&_ccond);
pthread_mutex_unlock(&_mutex);

1.一個線程,在操作臨界資源的時候,必須臨界資源是滿足條件的!

2.可是,公共資源是否滿足生產(chǎn)或者消費條件,我們無法、直接得知【我們不能事前得知【在沒有訪問之前,無法得知】】

3.只能先加鎖,再檢測,再操作,再解鎖。因為你要檢測,本質(zhì):也是在訪問臨界資源!

因為我們在操作臨界資源的時候,有可能不就緒但是,我們無法提前得知,所以,只能先加鎖,在檢測,根據(jù)檢測結(jié)果,決定下一步怎么走!

只要我們對資源進行整體加鎖,就默認(rèn)了,我們對這個資源整體使用。實際情況可能存在:.一份公共資源,但是允許同時訪問不同的區(qū)域!程序員編碼保證不同的線程可以并發(fā)訪問公共資源的不同區(qū)域!

什么是信號量:

a.信號量本質(zhì)是一把計數(shù)器。衡量臨界資源中資源數(shù)量多少的計數(shù)器

b.只要擁有信號量,就在未來一定能夠擁有臨界資源的一部分,申請信號量的本質(zhì):對臨界資源中特定小塊資源的預(yù)訂機制

線程要訪問臨界資源中的某一區(qū)域–申請信號量–所有人必須的先看到信號量–信號量本身必須是:公共資源

有可能,我們在訪問真正的臨界資源之前,我們其實就可以提前知道臨界資源的使用情況! ! !

信號量只要申請成功,就一定有你的資源。只要申請失敗,就說明條件不就緒,你只能等!!不需要在判斷了!

計數(shù)器–遞減or 遞增sem_t sem = 10;

sem–;—申請資源—必須保證操作的原子性— P

sem++;—歸還資源—必須保證操作的原子性----V

信號量核心操作:PV原語

POSIX信號量和SystemV信號量作用相同,都是用于同步操作,達(dá)到無沖突的訪問共享資源目的。 但POSIX可以用于線程間同步。

初始化信號量

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
參數(shù):
pshared:0表示線程間共享,非零表示進程間共享
value:信號量初始值

銷毀信號量

int sem_destroy(sem_t *sem);

等待信號量

功能:等待信號量,會將信號量的值減1
int sem_wait(sem_t *sem); //P()

發(fā)布信號量

功能:發(fā)布信號量,表示資源使用完畢,可以歸還資源了。將信號量值加1。
int sem_post(sem_t *sem);//V()

四、基于環(huán)形隊列的生產(chǎn)消費模型

環(huán)形隊列采用數(shù)組模擬,用模運算來模擬環(huán)狀特性

【Linux】生產(chǎn)者消費者模型(阻塞隊列與環(huán)形隊列)和POSIX信號量,Linux系統(tǒng)編程,linux,生產(chǎn)者消費者模型,阻塞隊列,環(huán)形隊列,POSIX信號量,多線程

環(huán)形結(jié)構(gòu)起始狀態(tài)和結(jié)束狀態(tài)都是一樣的,不好判斷為空或者為滿,所以可以通過加計數(shù)器或者標(biāo)記位來判斷滿或者空。另外也可以預(yù)留一個空的位置,作為滿的狀態(tài)

【Linux】生產(chǎn)者消費者模型(阻塞隊列與環(huán)形隊列)和POSIX信號量,Linux系統(tǒng)編程,linux,生產(chǎn)者消費者模型,阻塞隊列,環(huán)形隊列,POSIX信號量,多線程

但是我們現(xiàn)在有信號量這個計數(shù)器,就很簡單的進行多線程間的同步過程

生產(chǎn)和消費在什么情況下可能訪問同一個位置:

1.空的時候

2.滿的時候

3.其他情況,生產(chǎn)者和消費者,根本訪問的就是不同的區(qū)域!

為了完成環(huán)形隊列cp問題,我們要做的核心工作是什么

1.你不能超過我

2我不能把你套一個圈以上

3.我們兩個什么時候,會站在一起?

信號量是用來衡量臨界資源中資源數(shù)量的

1.對于生產(chǎn)者而言,看中什么?隊列中的剩余空間—空間資源定義十個信號量

2.對于消費者而言,看中的是什么?放入隊列中的數(shù)據(jù)! —數(shù)據(jù)資源定義一個信號量

生產(chǎn)者而言:

prodocter_sem: 0
// 申請成功,你就可以繼續(xù)向下運行。
//申請失敗,當(dāng)前執(zhí)行流,阻塞在申請?zhí)?/span>
P(producter_sem);
//從事生產(chǎn)活動--把數(shù)據(jù)放入到隊列中
V(comsumer_sem);

消費者而言:

comsumer_sem:10
P(comsumer_sem);
//從事消費活動
v(producter_sem);_

未來,生產(chǎn)和消費的位置我們要想清楚:

1.其實就是隊列中的下標(biāo)、

2一定是兩個下標(biāo)

3.為空或者為滿,下標(biāo)相同文章來源地址http://www.zghlxwxcb.cn/news/detail-768050.html

1.RingQueue.hpp

#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <semaphore.h>

static const int gcap = 5;

template <class T>
class RingQueue
{
private:
    // 等待信號量,會將信號量的值減1
    void P(sem_t &sem)
    {
        int n = sem_wait(&sem);
        assert(n == 0);
        (void)n;
    }
    // 發(fā)布信號量,表示資源使用完畢,可以歸還資源了。將信號量值加1。
    void V(sem_t &sem)
    {
        int n = sem_post(&sem);
        assert(n == 0);
        (void)n;
    }

public:
    RingQueue(const int &cap = gcap)
        : _queue(cap), _cap(cap)
    {
        int n = sem_init(&_spaceSem, 0, _cap);
        assert(n == 0);
        n = sem_init(&_dataSem, 0, 0);
        assert(n == 0);

        _productorStep = _consumerStep = 0;

        pthread_mutex_init(&_pmutex, nullptr);
        pthread_mutex_init(&_cmutex, nullptr);
    }

    // 生產(chǎn)者
    void push(const T &in)
    {
        P(_spaceSem);
        pthread_mutex_lock(&_pmutex);
        _queue[_productorStep++] = in;
        _productorStep %= _cap;
        pthread_mutex_unlock(&_pmutex);
        V(_dataSem);
    }

    // 消費者
    void pop(T *out)
    {
        P(_dataSem);
        pthread_mutex_lock(&_cmutex);
        *out = _queue[_consumerStep++];
        _consumerStep %= _cap;
        pthread_mutex_unlock(&_cmutex);
        V(_spaceSem);
    }
    ~RingQueue()
    {
        sem_destroy(&_spaceSem);
        sem_destroy(&_dataSem);

        pthread_mutex_destroy(&_pmutex);
        pthread_mutex_destroy(&_cmutex);
    }

private:
    std::vector<T> _queue;
    int _cap;
    sem_t _spaceSem; // 生產(chǎn)者 想生產(chǎn),看中的是什么資源呢? 空間資源
    sem_t _dataSem;  // 消費者 想消費,看中的是什么資源呢? 數(shù)據(jù)資源
    int _productorStep;
    int _consumerStep;
    pthread_mutex_t _pmutex;
    pthread_mutex_t _cmutex;
};

2.Task.hpp

#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <functional>

class Task
{
    using func_t = std::function<int(int,int,char)>;
    // typedef std::function<int(int,int)> func_t;
public:
    Task()
    {}
    Task(int x, int y, char op, func_t func)
    :_x(x), _y(y), _op(op), _callback(func)
    {}
    std::string operator()()
    {
        int result = _callback(_x, _y, _op);
        char buffer[1024];
        snprintf(buffer, sizeof buffer, "%d %c %d = %d", _x, _op, _y, result);
        return buffer;
    }
    std::string toTaskString()
    {
        char buffer[1024];
        snprintf(buffer, sizeof buffer, "%d %c %d = ?", _x, _op, _y);
        return buffer;
    }
private:
    int _x;
    int _y;
    char _op;
    func_t _callback;
};

const std::string oper = "+-*/%";

int mymath(int x, int y, char op)
{
    int result = 0;
    switch (op)
    {
    case '+':
        result = x + y;
        break;
    case '-':
        result = x - y;
        break;
    case '*':
        result = x * y;
        break;
    case '/':
    {
        if (y == 0)
        {
            std::cerr << "div zero error!" << std::endl;
            result = -1;
        }
        else
            result = x / y;
    }
        break;
    case '%':
    {
        if (y == 0)
        {
            std::cerr << "mod zero error!" << std::endl;
            result = -1;
        }
        else
            result = x % y;
    }
        break;
    default:
        // do nothing
        break;
    }

    return result;
}

3.main.cc

#include "RingQueue.hpp"
#include "Task.hpp"
#include <pthread.h>
#include <ctime>
#include <cstdlib>
#include <sys/types.h>
#include <unistd.h>

std::string SelfName()
{
    char name[128];
    snprintf(name, sizeof(name), "thread[0x%x]", pthread_self());
    return name;
}

void *ProductorRoutine(void *rq)
{
    // RingQueue<int> *ringqueue = static_cast<RingQueue<int> *>(rq);
    RingQueue<Task> *ringqueue = static_cast<RingQueue<Task> *>(rq);
    while (true)
    {
        // version1
        // int data = rand() % 10 + 1;
        // ringqueue->Push(data);
        // std::cout << "生產(chǎn)完成,生產(chǎn)的數(shù)據(jù)是:" << data << std::endl;

        // version2
        // 構(gòu)建or獲取任務(wù) --- 這個是要花時間的!
        int x = rand() % 10;
        int y = rand() % 5;
        char op = oper[rand() % oper.size()];
        Task t(x, y, op, mymath);
        // 生產(chǎn)任務(wù)
        ringqueue->push(t);
        // 輸出提示
        std::cout << SelfName() << ", 生產(chǎn)者派發(fā)了一個任務(wù): " << t.toTaskString() << std::endl;

        // sleep(1);
    }
}

void *ConsumerRoutine(void *rq)
{
    // RingQueue<int> *ringqueue = static_cast<RingQueue<int> *>(rq);
    RingQueue<Task> *ringqueue = static_cast<RingQueue<Task> *>(rq);

    while (true)
    {
        // version1
        //  int data;
        //  ringqueue->Pop(&data);
        //  std::cout << "消費完成,消費的數(shù)據(jù)是:" << data << std::endl;
        //  sleep(1);

        // version2
        Task t;
        // 消費任務(wù)
        ringqueue->pop(&t);
        std::string result = t(); // 消費也是要花時間的!
        std::cout << SelfName() << ", 消費者消費了一個任務(wù): " << result << std::endl;

        // sleep(1);
    }
}

int main()
{
    srand((unsigned int)time(nullptr) ^ getpid() ^ pthread_self() ^ 0x71727374);
    // RingQueue<int> *rq = new RingQueue<int>();
    RingQueue<Task> *rq = new RingQueue<Task>();

    // 單生產(chǎn),單消費,多生產(chǎn),多消費 --> 只要保證,最終進入臨界區(qū)的是一個生產(chǎn),一個消費就行!
    // 多生產(chǎn),多消費的意義??
    pthread_t p[4], c[8];
    for (int i = 0; i < 4; i++)
        pthread_create(p + i, nullptr, ProductorRoutine, rq);
    for (int i = 0; i < 8; i++)
        pthread_create(c + i, nullptr, ConsumerRoutine, rq);

    for (int i = 0; i < 4; i++)
        pthread_join(p[i], nullptr);
    for (int i = 0; i < 8; i++)
        pthread_join(c[i], nullptr);
    delete rq;
    return 0;
}

到了這里,關(guān)于【Linux】生產(chǎn)者消費者模型(阻塞隊列與環(huán)形隊列)和POSIX信號量的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

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

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

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

    2024年02月11日
    瀏覽(26)
  • 【Linux】生產(chǎn)者消費者模型代碼實現(xiàn)和信號量

    【Linux】生產(chǎn)者消費者模型代碼實現(xiàn)和信號量

    一定要先理解生產(chǎn)者消費者模型的原理~ 文章目錄 一、生產(chǎn)者消費者模型實現(xiàn)代碼 二、信號量 1.基于環(huán)形隊列的生產(chǎn)者消費者模型 總結(jié) 下面我們實現(xiàn)基于阻塞隊列的生產(chǎn)消費模型: 在多線程編程中阻塞隊列 (Blocking Queue) 是一種常用于實現(xiàn)生產(chǎn)者和消費者模型的數(shù)據(jù)結(jié)構(gòu)。其

    2024年02月11日
    瀏覽(20)
  • 【linux】線程同步+基于BlockingQueue的生產(chǎn)者消費者模型

    【linux】線程同步+基于BlockingQueue的生產(chǎn)者消費者模型

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

    2024年02月03日
    瀏覽(24)
  • Linux之信號量 | 消費者生產(chǎn)者模型的循環(huán)隊列

    Linux之信號量 | 消費者生產(chǎn)者模型的循環(huán)隊列

    目錄 一、信號量 1、概念 2、信號量操作函數(shù) 二、基于環(huán)形隊列的生產(chǎn)者消費者模型 1、模型分析 2、代碼實現(xiàn) 1、單生產(chǎn)單消費的生產(chǎn)者消費者模型 2、多生產(chǎn)多消費的生產(chǎn)者消費者模型 引入:前面我們講到了,對臨界資源進行訪問時,為了保證數(shù)據(jù)的一致性,我們需要對臨

    2024年04月17日
    瀏覽(27)
  • 『Linux』第九講:Linux多線程詳解(四)_ 生產(chǎn)者消費者模型

    『Linux』第九講:Linux多線程詳解(四)_ 生產(chǎn)者消費者模型

    「前言」文章是關(guān)于Linux多線程方面的知識,上一篇是?Linux多線程詳解(三),今天這篇是 Linux多線程詳解(四),內(nèi)容大致是生產(chǎn)消費者模型,講解下面開始! 「歸屬專欄」Linux系統(tǒng)編程 「主頁鏈接」個人主頁 「筆者」楓葉先生(fy) 「楓葉先生有點文青病」「每篇一句」

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

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

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

    2024年02月02日
    瀏覽(29)
  • 【Linux】線程同步 -- 條件變量 | 生產(chǎn)者消費者模型 | 自旋鎖 |讀寫鎖

    【Linux】線程同步 -- 條件變量 | 生產(chǎn)者消費者模型 | 自旋鎖 |讀寫鎖

    舉一個例子: 學(xué)生去超市消費的時候,與廠家生產(chǎn)的時候,兩者互不相沖突。 生產(chǎn)的過程與消費的過程 – 解耦 臨時的保存產(chǎn)品的場所(超時) – 緩沖區(qū) 模型總結(jié)“321”原則: 3種關(guān)系:生產(chǎn)者和生產(chǎn)者(互斥),消費者和消費者(互斥),生產(chǎn)者和消費者(互斥[保證共享資

    2024年02月14日
    瀏覽(25)
  • 《Linux從練氣到飛升》No.29 生產(chǎn)者消費者模型

    ??作者: 主頁 我的專欄 C語言從0到1 探秘C++ 數(shù)據(jù)結(jié)構(gòu)從0到1 探秘Linux 菜鳥刷題集 ??歡迎關(guān)注:??點贊??收藏??留言 ?? 碼字不易,你的??點贊??收藏??關(guān)注對我真的很重要,有問題可在評論區(qū)提出,感謝閱讀!??!

    2024年02月05日
    瀏覽(20)
  • 線程池-手寫線程池Linux C簡單版本(生產(chǎn)者-消費者模型)

    線程池-手寫線程池Linux C簡單版本(生產(chǎn)者-消費者模型)

    本線程池采用C語言實現(xiàn) 線程池的場景: 當(dāng)某些任務(wù)特別耗時(例如大量的IO讀寫操作),嚴(yán)重影響線程其他的任務(wù)的執(zhí)行,可以使用線程池 線程池的一般特點: 線程池通常是一個生產(chǎn)者-消費者模型 生產(chǎn)者線程用于發(fā)布任務(wù),任務(wù)通常保存在任務(wù)隊列中 線程池作為消費者,

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

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

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

    2023年04月08日
    瀏覽(43)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包