동시에 실행되고, 버퍼의 크기가 제한되어있고, 두 주체 처리의 속도가 다를 때 다음 문제들이 발생한다.-> 따라서 생산자와 소비자는 동기화(Synchronization)를 통해 서로의 작업을 조율해야 한다.
읽기용 세마포어 :읽을 데이터가 있을 때만 소비자가 접근하도록 제어쓰기용 세마포어 :빈 공간이 있을 때만 생산자가 접근하도록 제어뮤텍스 :생산자 :소비자 :
#include <thread>
#include <iostream>
#include <vector>
#include <mutex>
#include<cstdio>
#include<queue>
#include <string>
#include <chrono>
using std::thread;
using std::vector;
void producer(std::queue<std::string>* downloaded_pages, std::mutex* m, int index)
{
for (int i = 0; i < 5; i++)
{
//웹사이트 다운로드하는데 걸리는 시간
//각 쓰레드별로 다운로드하는데 걸리는 시간다르다.
std::this_thread::sleep_for(std::chrono::milliseconds(100 * index));
std::string content = "웹사이트 : " + std::to_string(i) + "from thread{" + std::to_string(index) + ")\n";
//데이터는 쓰레드에서 공유되므로 critical section에 넣어야 함
m->lock();
downloaded_pages->push(content);
m->unlock();
}
}
void consumer(std::queue<std::string>* downloaded_pages, std::mutex* m, int* num_processed)
{
//전체 처리하는 페이지 개수가 5 * 5 =25개
while (*num_processed < 25)
{
m->lock();
//만일 현재 다운로드한 페이지가 없다면 다시 대기
if (downloaded_pages->empty())
{
m->unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
//맨 앞페이지 읽어온 후 처리
std::string content = downloaded_pages->front();
downloaded_pages->pop();
(*num_processed)++;
m->unlock();
//content 처리한다.
std::cout << content;
std::this_thread::sleep_for(std::chrono::milliseconds(80));
}
}
int main()
{
//현재 다운로드한 페이지들 리스트로, 아직 처리되지 않은 것들이다.
std::queue<std::string> downloaded_pages;
std::mutex m;
std::vector<std::thread> producers;
for (int i = 0; i < 5; i++)
{
producers.push_back(std::thread(producer, &downloaded_pages, &m, i + 1));
}
int num_processed = 0;
std::vector<std::thread> consumers;
for (int i = 0; i < 3; i++)
{
consumers.push_back(std::thread(consumer, &downloaded_pages, &m, &num_processed));
}
for (int i = 0; i < 5; i++)
producers[i].join();
for (int i = 0; i < 3; i++)
consumers[i].join();
}