찾다
백엔드 개발C#.Net 튜토리얼C++ 솔루션: 다중 스레드 동기화의 전형적인 사례: 생산자-소비자 문제

Wikipedia에서 복사됨:

생산자-소비자 문제(영어: 생산자-소비자 문제)는 Bounded-buffer 문제(영어: Bounded-buffer 문제)라고도 알려져 있으며 다중 스레드 동기화의 전형적인 사례입니다. 문제 . 이 질문은 고정 크기 버퍼를 공유하는 두 스레드(소위 "생산자"와 "소비자")가 실제로 실행될 때 발생하는 문제를 설명합니다. 생산자의 주요 역할은 일정량의 데이터를 생성하여 버퍼에 넣은 후 프로세스를 반복하는 것입니다. 동시에 소비자도 버퍼의 데이터를 소비하고 있습니다. 이 문제의 핵심은 버퍼가 가득 찼을 때 생산자가 데이터를 추가하지 않고, 버퍼가 비어 있을 때 소비자가 데이터를 소비하지 않도록 하는 것입니다.

이 문제를 해결하려면 버퍼가 가득 찼을 때 생산자를 절전 모드로 전환해야 합니다(또는 간단히 데이터를 포기해야 함). 다음에 소비자가 버퍼의 데이터를 소비할 때 생산자가 깨어나서 버퍼를 시작할 수 있습니다. 데이터를 추가합니다. 마찬가지로, 버퍼가 비어 있으면 소비자를 절전 모드로 전환하고 생산자가 버퍼에 데이터를 추가할 때까지 기다린 다음 소비자를 깨울 수도 있습니다.

이 기사에서는 ItemRepository 클래스를 사용하여 좌표로 표시되는 배열과 두 개의 순환 큐가 포함된 제품 창고를 나타내고 std::mutex 멤버를 사용하여 한 번에 하나의 스레드에서만 읽고 쓸 수 있도록 합니다( 인쇄된 메시지가 한 줄씩 전송되고 유휴 상태일 때 뮤텍스 ╮(╯▽╰)╭)도 차용되도록 하기 위해 두 개의 std::condition_variables는 만족되지 않은 대기열의 상태를 나타냅니다. 비어 있으므로 생산 중에 대기열이 만족되지 않고 소비됩니다.

#pragma once
#include <chrono>//std::chrono
#include <mutex>//std::mutex,std::unique_lock,std::lock_guard
#include <thread>//std::thread
#include <condition_variable>//std::condition_variable
#include <iostream>//std::cout,std::endl
#include <map>//std::map
namespace MyProducerToConsumer {
    static const int gRepositorySize = 10;//total size of the repository
    static const int gItemNum = 97;//number of products to produce
    std::mutex produce_mtx, consume_mtx;//mutex for all the producer thread or consumer thread
    std::map<std::thread::id, int> threadPerformance;//records of every thread&#39;s producing/consuming number
    struct ItemRepository {//repository class
        int m_ItemBuffer[gRepositorySize];//Repository itself (as a circular queue)
        int m_ProducePos;//rear position of circular queue
        int m_ConsumePos;//head position of circular queue
        std::mutex m_mtx;//mutex for operating the repository
        std::condition_variable m_RepoUnfull;//indicating that this repository is unfull(then producers can produce items)
        std::condition_variable m_RepoUnempty;//indicating that this repository is unempty(then consumers can produce items)
    }gItemRepo;

    void ProduceItem(ItemRepository *ir, int item) {
        std::unique_lock <std::mutex>ulk(ir->m_mtx);
        while ((ir->m_ProducePos + 1) % gRepositorySize == ir->m_ConsumePos) {//full(spare one slot for indicating)
            std::cout << "Reposity is full. Waiting for consumers..." << std::endl;
            ir->m_RepoUnfull.wait(ulk);//unlocking ulk and waiting for unfull condition
        }
        //when unfull
        ir->m_ItemBuffer[ir->m_ProducePos++] = item;//procude and shift
        std::cout << "Item No." << item << " produced successfully by "
            <<std::this_thread::get_id()<<"!" << std::endl;
        threadPerformance[std::this_thread::get_id()]++;
        if (ir->m_ProducePos == gRepositorySize)//loop
            ir->m_ProducePos = 0;
        ir->m_RepoUnempty.notify_all();//item produced, so it&#39;s unempty; notify all consumers
    }

    int ConsumeItem(ItemRepository *ir) {
        std::unique_lock<std::mutex>ulk(ir->m_mtx);
        while (ir->m_ConsumePos == ir->m_ProducePos) {//empty
            std::cout << "Repository is empty.Waiting for producing..." << std::endl;
            ir->m_RepoUnempty.wait(ulk);
        }
        int item = ir->m_ItemBuffer[ir->m_ConsumePos++];
        std::cout << "Item No." << item << " consumed successfully by "
            <<std::this_thread::get_id()<<"!" << std::endl;
        threadPerformance[std::this_thread::get_id()]++;
        if (ir->m_ConsumePos == gRepositorySize)
            ir->m_ConsumePos = 0;
        ir->m_RepoUnfull.notify_all();//item consumed, so it&#39;s unempty; notify all consumers
        return item;
    }

    void ProducerThread() {
        static int produced = 0;//static variable to indicate the number of produced items
        while (1) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));//sleep long enough in case it runs too fast for other threads to procude
            std::lock_guard<std::mutex>lck(produce_mtx);//auto unlock when break
            produced++;
            if (produced > gItemNum)break;
            gItemRepo.m_mtx.lock();
            std::cout << "Producing item No." << produced << "..." << std::endl;
            gItemRepo.m_mtx.unlock();
            ProduceItem(&gItemRepo, produced);
        }
        gItemRepo.m_mtx.lock();
        std::cout << "Producer thread " << std::this_thread::get_id()
            << " exited." << std::endl;
        gItemRepo.m_mtx.unlock();
    }

    void ConsumerThread() {
        static int consumed = 0;
        while (1) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            std::lock_guard<std::mutex>lck(consume_mtx);
            consumed++;
            if (consumed > gItemNum)break;
            gItemRepo.m_mtx.lock();
            std::cout << "Consuming item available..." << std::endl;
            gItemRepo.m_mtx.unlock();
            ConsumeItem(&gItemRepo);
        }
        gItemRepo.m_mtx.lock();
        std::cout << "Consumer thread " << std::this_thread::get_id()
            << " exited." << std::endl;
        gItemRepo.m_mtx.unlock();
    }

    void InitItemRepository(ItemRepository* ir) {
        ir->m_ConsumePos = 0;
        ir->m_ProducePos = 0;
    }

    void Run() {
        InitItemRepository(&gItemRepo);
        std::thread thdConsume[11];
        std::thread thdProduce[11];
        for (auto& t : thdConsume)t = std::thread(ConsumerThread);
        for (auto& t : thdProduce)t = std::thread(ProducerThread);
        for (auto& t : thdConsume)t.join();
        for (auto& t : thdProduce)t.join();
        for (auto& iter : threadPerformance)cout << iter.first << ":" << iter.second << endl;
    }
}

관련 기사:

Java 생산자와 소비자의 자세한 예

Java 다중 스레드 동시 협업 생산자-소비자 디자인 패턴

위 내용은 C++ 솔루션: 다중 스레드 동기화의 전형적인 사례: 생산자-소비자 문제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
C 언어로 Null의 대안은 무엇입니까?C 언어로 Null의 대안은 무엇입니까?Mar 03, 2025 pm 05:37 PM

이 기사는 C의 Null 포인터 단축의 도전에 대해 탐구합니다. 그것은 문제가 그 자체가 아니라 오용한다고 주장합니다. 이 기사는 사전 수준 점검, 포인터 이니셜을 포함한 수반을 방지하기위한 모범 사례에 대해 자세히 설명합니다.

어떤 C 언어 컴파일러가 더 낫습니까?어떤 C 언어 컴파일러가 더 낫습니까?Mar 03, 2025 pm 05:39 PM

이 기사는 초보자가 C 컴파일러를 선택하도록 안내합니다. GCC는 사용 편의성, 광범위한 가용성 및 광범위한 리소스로 인해 초보자에게 가장 적합하다고 주장합니다. 그러나 GCC, Clang, MSVC 및 TCC도 비교하여 차이를 강조합니다.

차세대 C 컴파일러를 추가하는 방법차세대 C 컴파일러를 추가하는 방법Mar 03, 2025 pm 05:44 PM

이 기사에서는 printf 내에서 \ n 탈출 시퀀스를 사용하여 C에서 Newline 문자를 만드는 방법을 설명하고 함수를 넣습니다. 기능을 자세히 설명하고 출력에서 ​​라인 브레이크 사용을 보여주는 코드 예제를 제공합니다.

Null은 C 언어로 된 현대 프로그래밍에서 여전히 중요합니까?Null은 C 언어로 된 현대 프로그래밍에서 여전히 중요합니까?Mar 03, 2025 pm 05:35 PM

이 기사는 현대 C 프로그래밍에서 NULL의 지속적인 중요성을 강조합니다. 발전에도 불구하고 NULL은 명시적인 포인터 관리에 중요하며, 유효한 메모리 주소가 없음을 표시하여 세분화 결함을 방지합니다. 최고의 PRAC

C 언어 컴파일러의 웹 버전은 무엇입니까?C 언어 컴파일러의 웹 버전은 무엇입니까?Mar 03, 2025 pm 05:42 PM

이 기사에서는 초보자를위한 온라인 C 컴파일러를 검토하여 사용 편의성 및 디버깅 기능에 중점을 둡니다. OnlineGDB 및 Repl.it는 사용자 친화적 인 인터페이스 및 유용한 디버깅 도구를 위해 강조 표시됩니다. 프로그램 및 컴파일과 같은 다른 옵션

C 언어 온라인 프로그래밍 웹 사이트 C 언어 컴파일러 공식 웹 사이트 요약C 언어 온라인 프로그래밍 웹 사이트 C 언어 컴파일러 공식 웹 사이트 요약Mar 03, 2025 pm 05:41 PM

이 기사는 온라인 C 프로그래밍 플랫폼을 비교하여 디버깅 도구, IDE 기능, 표준 컴플라이언스 및 메모리/실행 제한과 같은 기능의 차이점을 강조합니다. "최고의"플랫폼은 사용자의 요구에 달려 있다고 주장합니다.

C 언어 컴파일러에 의해 코드를 복사하는 방법C 언어 컴파일러에 의해 코드를 복사하는 방법Mar 03, 2025 pm 05:43 PM

이 기사에서는 C IDE의 효율적인 코드 복사에 대해 설명합니다. 복사는 컴파일러 기능이 아닌 IDE 기능이며 IDE 선택 도구 사용, 코드 폴딩, 검색/교체, Templa를 포함하여 효율성 향상을위한 세부 사항 전략을 강조합니다.

C 언어 컴파일러에 의해 출력 창을 팝업하지 않는 문제를 해결하는 방법C 언어 컴파일러에 의해 출력 창을 팝업하지 않는 문제를 해결하는 방법Mar 03, 2025 pm 05:40 PM

이 기사는 C 프로그램 컴파일에서 누락 된 출력 창을 문제 해결합니다. 실행 가능, 프로그램 오류, 잘못된 컴파일러 설정, 백그라운드 프로세스 및 빠른 프로그램 종료와 같은 원인을 검사합니다. 솔루션은 ch

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)