c++다 중 스 레 드 는 왜 조건 변 수 를 사용 하 는 지 상세 하 게 설명 합 니 다.
#include <iostream>
#include <windows.h>
#include <mutex>
#include<deque>
#include <thread>
using namespace std;
int nmax = 20;
std::deque<int> m_que;
std::mutex mymutex;
//
void producterex()
{
int i = 1;
while (i<nmax)
{
//
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<mutex> lcx(mymutex);
m_que.push_back(i);
cout << "producted:" << i << endl;
lcx.unlock();
i++;
}
cout << "product thread exit
";
}
//
void consumerex()
{
int i = 0;
while (1)
{
std::unique_lock<mutex> lcx(mymutex);
if (!m_que.empty())
{
int i = m_que.back();
m_que.pop_back();
cout << "consumed:" << i << endl;
lcx.unlock();
i++;
if (i == nmax)
{
break;
}
}
else
{
lcx.unlock();
}
}
cout << "consumerex thread exit
";
}
void main()
{
std::thread t1(producterex);
std::thread t2(consumerex);
t1.detach();
cout << "hello";
t2.detach();
cout << " world!
";
getchar();
system("pause");
}
결과:cpu 사용률 이 매우 높다 는 것 을 알 수 있다.높 은 이 유 는 주로 소비자 스 레 드 에 있 습 니 다.대기 열 이 비어 있 을 때 도 실행 해 야 하기 때 문 입 니 다.너무 많은 무공 해 를 해서 CPU 점유 율 이 너무 높 기 때문에 다음 에 개조 하여 비 어 있 을 때 200 밀리초 를 기다 리 게 하 는 것 은 폴 링 간격 주 기 를 확대 하 는 것 과 같 습 니 다.CPU 의 점용 률 을 낮 출 수 있어 야 합 니 다.
다른 것 은 모두 같 기 때문에 여기에 소비자 의 라인 을 붙인다.
//
void consumerex()
{
int i = 0;
while (1)
{
std::unique_lock<mutex> lcx(mymutex);
if (!m_que.empty())
{
int i = m_que.back();
m_que.pop_back();
cout << "consumed:" << i << endl;
lcx.unlock();
i++;
if (i == nmax)
{
break;
}
}
else
{
lcx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
cout << "consumerex thread exit
";
}
결과:이 를 통 해 알 수 있 듯 이 CPU 점용 률 이 단번에 떨 어 졌 다.
여기 서 어려움 이 있 습 니 다.휴면 시간 간격(즉,폴 링 간격 주기)을 어떻게 정 하 는 지 입 니 다.간격 이 너무 짧 으 면 CPU 자원 을 너무 많이 차지 하고 간격 이 너무 길 면 제때에 응답 하지 못 해 지연 될 수 있 습 니 다.
이 는 조건 변 수 를 도입 하여 이 문 제 를 해결 했다.조건 변 수 는'알림-깨 우기'모델 을 사용 하고 생산 자 는 하나의 데 이 터 를 생산 한 후에 소비자 에 게 사용 하 라 고 알 리 며 소비자 가 통 지 를 받 지 않 기 전에 휴면 상태 에서 CPU 자원 을 절약 하도록 한다.소비자 가 통 지 를 받 은 후에 얼른 휴면 상태 에서 깨 어 나 데 이 터 를 처리 하고 사건 구동 모델 을 사용 하여 일 을 그 르 치지 않도록 하 는 상황 에서 자원 에 대한 소 모 를 최대한 줄 였 다.
condition_variable 소개
C++11 에서 조건 변수(conditionvariable)여러 스 레 드 간 의 동기 화 작업 을 실현 합 니 다.조건 이 만족 하지 않 을 때 관련 스 레 드 는 특정한 조건 이 나타 날 때 까지 계속 막 혀 야 이 스 레 드 들 이 깨 어 날 수 있다.
구성원 함 수 는 다음 과 같 습 니 다.
조건 변 수 는 스 레 드 간 에 공 유 된 전역 변 수 를 이용 하여 동기 화 하 는 메커니즘 으로 주로 두 가지 동작 을 포함한다.
a.하나의 스 레 드 는'조건 변수의 조건 이 성립 되 기 를 기다 리 기 때문에 걸 립 니 다.
b.다른 스 레 드 는'조건 이 성립'되 고 신 호 를 보 내 서 기다 리 는 스 레 드 를 깨 웁 니 다.
경쟁 을 방지 하기 위해 조건 변수의 사용 은 항상 상호 배척 자물쇠 와 결합 된다.일반적인 상황 에서 이 자 물 쇠 는 std:mutex 이 고 이 자 물 쇠 를 관리 하 는 것 은 std::unique 일 수 밖 에 없습니다.lockstd::mutex RAII 템 플 릿 클래스 입 니 다.
위 에서 언급 한 두 가지 절 차 는 다음 과 같은 두 가지 방법 으로 이 루어 진다.
1.대기 조건 성립 시 condition 사용variable 클래스 구성원 wait,waitfor 또는 waituntil。
2.신 호 를 보 내 는 것 은 conditionvariable 클래스 구성원 notifyone 또는 notifyall 함수.
상기 두 가지 유형의 wait 함수 가 모두 막 힐 때 자동 으로 잠 금 권한 을 방출 합 니 다.즉,유 니 크 를 호출 합 니 다.lock 의 구성원 함수 unlock()은 다른 스 레 드 가 자 물 쇠 를 얻 을 수 있 도록 합 니 다.이것 이 바로 조건 변수 와 유 니 크lock 과 함께 사용 하 는 이유 입 니 다.그렇지 않 으 면 현재 스 레 드 가 계속 자 물 쇠 를 차지 하고 스 레 드 가 막 힙 니 다.
거짓 각성
정상 적 인 상황 에서 wait 유형 함수 가 되 돌아 올 때 깨 어 나 거나 시간 이 초과 되 어서 되 돌아 오지 않 으 면==실제 에서 발견 되 기 때문에 운영 체제 의 원인,wait 유형 이 조건 을 만족 시 키 지 못 할 때 되 돌아 와 허위 각성 을 초래 합 니 다.==따라서,우 리 는 일반적으로 서술 어 파 라 메 터 를 가 진 wait 함 수 를 사용 합 니 다.왜냐하면 이러한(xxx,Predicate pred)유형의 함수 가 다음 과 같 기 때 문 입 니 다.
while (!pred()) //while ,
{
wait(lock);
}
원인 설명 은 다음 과 같다.시스템 에 허위 각성 이 존재 하지 않 는 다 고 가정 할 때 코드 형식 은 다음 과 같다.
if ( xxx )
{
// ,wait , , 。
// , ,wait , if ,
// ,
wait();
}
//
...
올 바른 사용 방식,while 문 구 를 사용 하여 해결:
while (!(xxx ) )
{
// , while , ,
// ,
wait();
}
//
....
조건 변 수 를 사용 하 는 상황 을 살 펴 보 겠 습 니 다.
#include <iostream>
#include <windows.h>
#include <mutex>
#include<deque>
#include <thread>
#include<condition_variable>
using namespace std;
int nmax = 10;
std::deque<int> m_que;
std::mutex mymutex;
condition_variable mycv;
//
void producterex()
{
int i = 1;
while (i<nmax)
{
//
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<mutex> lcx(mymutex);
m_que.push_back(i);
cout << "producted:" << i << endl;
lcx.unlock();
mycv.notify_one();
i++;
}
cout << "product thread exit
";
}
//
bool m_bflag = false;
void consumerex()
{
int i = 0;
bool m_bexit = false;
while (!m_bexit)
{
std::unique_lock<mutex> lcx(mymutex);
while (m_que.empty())
{
//
mycv.wait(lcx);
if (m_bflag)
{
cout << "consumerex thread exit
";
m_bexit = true;
break;
}
}
if (m_bexit)
{
break;
}
int i = m_que.back();
m_que.pop_back();
lcx.unlock();
cout << "consumed:" << i << endl;
}
cout << "consumerex thread exit
";
}
void main()
{
std::thread t1(producterex);
std::thread t2(consumerex);
t1.detach();
cout << "hello";
t2.detach();
cout << " world!
";
mycv.notify_one();
Sleep(15000);
m_que.push_back(100);
mycv.notify_one();
Sleep(3000);
m_bflag = true;
mycv.notify_one();//
getchar();
system("pause");
}
결과:mycv.wait(lcx)도 가능 합 니 다.쓰기 방법 을 바 꾸 면 wait()의 두 번 째 매개 변 수 는 하나의 함수 로 검사 조건 을 표시 할 수 있 습 니 다.여 기 는 lambda 함 수 를 사용 하 는 것 이 가장 간단 합 니 다.만약 에 이 함수 가 true 로 돌아 오 면 wait()함수 가 막 히 지 않 고 바로 돌아 갑 니 다.만약 에 이 함수 가 false 로 돌아 오 면 wait()함수 가 깨 어 나 기 를 기다 리 는 것 을 막 을 것 입 니 다.만약 에 위 에서 깨 어 나 면 함수 반환 값 을 계속 판단 할 것 입 니 다.코드 예 시 는 다음 과 같다.
#include <iostream>
#include <windows.h>
#include <mutex>
#include<deque>
#include <thread>
#include<condition_variable>
using namespace std;
int nmax = 10;
std::deque<int> m_que;
std::mutex mymutex;
condition_variable mycv;
//
void producterex()
{
int i = 1;
while (i<nmax)
{
//
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<mutex> lcx(mymutex);
m_que.push_back(i);
cout << "producted:" << i << endl;
lcx.unlock();
mycv.notify_one();
i++;
}
cout << "product thread exit
";
}
//
bool m_bflag = false;
void consumerex()
{
int i = 0;
while (1)
{
std::unique_lock<mutex> lcx(mymutex);
mycv.wait(lcx, [](){
// false
return !m_que.empty();
});
if (m_bflag)
{
break;
}
int i = m_que.back();
m_que.pop_back();
lcx.unlock();
cout << "consumed:" << i << endl;
}
cout << "consumerex thread exit
";
}
void main()
{
std::thread t1(producterex);
std::thread t2(consumerex);
t1.detach();
cout << "hello";
t2.detach();
cout << " world!
";
mycv.notify_one();
Sleep(15000);
m_que.push_back(100);
mycv.notify_one();
Sleep(3000);
m_bflag = true;
m_que.push_back(-1);
mycv.notify_one();//
getchar();
system("pause");
}
총결산
c++다 중 스 레 드 가 왜 조건 변 수 를 사용 하 는 지 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 c+다 중 스 레 드 조건 변수 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
HDU 원활 공사 & & 원활 공사 (차 트 법)모 성 은 도시 의 교통 상황 을 조사 하여 기 존의 도시 도로 통계 표를 얻 었 고 표 에는 모든 도로 가 직접 연 결 된 도시 가 열거 되 어 있다.성 정부의 '원활 한 공사' 목 표 는 성 전체의 어느 두 도시...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.