c++병렬 프로 그래 밍(5)-원자 유형 과 원자 조작 atomic
간단 한 예 를 들 어 원자 유형 을 사용 하 는 역할 을 살 펴 보 자.
std::atomic sum = 0;
//int sum = 0;
void fun()
{
for (int i = 0; i<100000; ++i)
sum ++; // sum
}
int main()
{
std::cout << "Before joining,sun = " << sum << std::endl;
std::thread t1(fun);
std::thread t2(fun);
t1.join();
t2.join();
std::cout << "After joining,sun = " << sum << std::endl;
system("pause");
return 0;
}
원자 형식 을 사용 하면 잠 금 이 없 는 스 레 드 간 데이터 공 유 를 완성 할 수 있 습 니 다.
가장 간단 한 표준 원자 유형 std::atomic플래그
// std::atomic_flag
class spinlock_mutex {
std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
spinlock_mutex() {}
void lock() {
while (flag.test_and_set(std::memory_order_acquire));
}
void unlock() {
flag.clear(std::memory_order_release);
}
};
eg:c+표준 은 자전 자 물 쇠 를 제공 하지 않 습 니 다.자 회전 자 물 쇠 는 다 중 스 레 드 공유 자원 을 보호 하 는 자물쇠 입 니 다.일반적인 상호 배척 자물쇠(mutex)와 다른 점 은 자 회전 자물쇠 가 자물쇠 의 소유권 을 가 져 오 려 고 할 때 바 쁜 대기(busy waiting)형식 으로 자물쇠 가 사용 가능 한 지 계속 순환 검사 하 는 것 입 니 다.다 중 프로세서 환경 에서 잠 금 시간 이 비교적 짧 은 프로그램 에 대해 서 는 일반적인 상호 배척 잠 금 대신 자전 자 물 쇠 를 사용 하면 프로그램의 성능 을 향상 시 킬 수 있다.
그 중에서 회색 사각형 의 3 단 계 는 분리 할 수 없 는 원자 조작 이 어야 한다.자전 자 물 쇠 를 풀 때 원자 조작 형식 으로 flag 를 false 로 설정 하면 됩 니 다.
std::atomic_flag 대상 은 두 가지 조작 만 포함 합 니 다-testand_set()&clear()-그리고 모두 원자 조작 입 니 다.
test_and_set()는 읽 기-수정-쓰기 동작 입 니 다.flag 가 false 일 때 성공 하면 true 로 돌아 갑 니 다.
clear()는 저장 작업 으로 flag 를 false 로 설정 합 니 다.
std::atomic
기본 유형(예 를 들 어 int,double*등)에 std::atomic 템 플 릿 을 원자 유형 으로 포장 하고 사용 할 수 있 는 원자 조작 은 load,store,exchange,compare 등 이 있 습 니 다.
원자 조작의 메모리 순서
프로그램 코드 를 최적화 하기 위해 컴 파 일 러 와 프로 세 서 는 상호 의존 관계 가 없 는 모든 명령 을 자 유 롭 게 다시 배열 할 수 있다.예 를 들 어 두 개의 분배 문 a=0;B=1;,그것들 은 어떤 순서 로 든 집행 할 수 있다.그러나 다 중 스 레 드 환경 에서 서로 다른 스 레 드 메모리 작업 간 의 의존성 은 컴 파일 러 나 프로세서 에 보이 지 않 기 때문에 컴 파일 러 나 프로세서 에 명령 을 실행 하고 정렬 하 는 데 오류 가 발생 할 수 있 습 니 다.원자 작업 의 메모리 순 서 를 제정 하여 스 레 드 간 원자 문맥 동기 화 결합 성 을 약화 시 켜 실행 효율 을 높 인 다.
기본 std::memory 대신 메모리 순 서 를 지정 합 니 다.order_seq_cst 는 성능 을 향상 시 킬 수 있다.C++11 의 std::memoryorder 는 여섯 개의 매 거 진 값 이 있 습 니 다.
Value
묘사 하 다.
std::memory_order_relaxed
동기 화 와 정렬 제한 이 없 으 며,조작 이 원자 라 는 것 만 보증 해 야 한다.
std::memory_order_consume
이 값 을 지정 한 load 작업 은 영향 을 받 는 메모리 위치 에서 consume 작업 을 수행 합 니 다.이 작업 은 같은 메모리 위치 에서 release 작업 을 수행 한 다른 스 레 드 가 그 전에 데이터 의존(data-dependent)메모리 위치 에 대한 쓰기 동작 을 현재 스 레 드 로 볼 수 있 습 니 다.
std::memory_order_acquire
이 값 을 지정 한 load 작업 은 영향 을 받 은 메모리 위치 에서 acquire 작업 을 수행 합 니 다.이 작업 은 같은 메모리 위치 에서 release 작업 을 수행 한 다른 스 레 드 를 현재 스 레 드 로 볼 수 있 습 니 다.
std::memory_order_release
이 값 을 지정 한 store 작업 은 영향 을 받 는 메모리 위치 에서 release 작업 을 수행 합 니 다.이 작업 은 이 스 레 드 전에 데이터 의존(data-dependent)의 메모리 위치 에 대한 쓰기 체 조 를 다른 메모리 위치 로 한 다음 에 같은 메모리 위치 에서 consume 작업 을 수행 하 는 라인 을 통 해 볼 수 있 습 니 다.이 스 레 드 전에 임의의 메모리 위치 에 대한 쓰기 체 조 를 다른 스 레 드 로 만 든 다음 같은 메모리 위치 에서 acquire 작업 을 수행 하 는 스 레 드 를 통 해 볼 수 있 습 니 다.
std::memory_order_acq_rel
이 값 을 지정 한 read-modify-write 작업 은 읽 기 단계(load 에 해당 함)에서 영향 을 받 는 메모리 위치 에 acquire 작업 을 수행 하고 쓰기 단계(store 에 해당 함)에서 같은 메모리 위치 에 release 작업 을 수행 합 니 다.
std::memory_order_seq_cst
순서 일치 성,모든 스 레 드 가 관찰 한 전체 프로그램 에서 메모리 수정 순서 가 일치 합 니 다.
순서 일치 성 순서 std:memoryorder_seq_cst
온라인 프로 세 스 a 에서\#1 작업 은\#2 전에 순서 일치 성 순 서 를 사용 하고 온라인 프로 세 스 b 에서 도 이 순서 로 간주 합 니 다.즉,순서 가 일치 하면 모든 스 레 드 간 의 전체 동기 화 를 요구한다.
std::atomic data;
std::atomic data_ready(false);
// a
void writer_thread()
{
data.store(10,std::memory_order_seq_cst); // #1: data
data_ready.store(true, std::memory_order_seq_cst); // #2: data_ready
}
// b
void reader_thread()
{
while (!data_ready.load(std::memory_order_seq_cst)) {} // #3: data_ready
std::cout << "data is "<< data.load(std::memory_order_seq_cst) << "
"; // #4: data
}
int main() {
std::thread a(reader_thread);
std::thread b(writer_thread);
a.join();
b.join();
system("pause");
}
느슨 한 순서 std::memoryorder_relaxed
이 때 스 레 드 b 에서 조작\#1 과 조작\#2 의 순서 가 정 해 지지 않 습 니 다.아마도 dataready 가 true 일 때 data 는 0 입 니 다.
std::atomic data;
std::atomic data_ready(false);
// a
void writer_thread()
{
data.store(10,std::memory_order_relaxed); // #1: data
data_ready.store(true, std::memory_order_relaxed); // #2: data_ready
}
// b
void reader_thread()
{
while (!data_ready.load(std::memory_order_relaxed)) {} // #3: data_ready
std::cout << "data is "<< data.load(std::memory_order_relaxed) << "
"; // #4: data
}
int main() {
std::thread b(writer_thread);
std::thread a(reader_thread);
a.join();
b.join();
system("pause");
}
획득-방출 순서 std::memoryorder_acquire&std::memory_order_release
느슨 한 순서 가 너무 자 유 롭 고 순서 일치 성 순서 가 너무 엄격 하기 때문에 석방 순 서 를 제공 합 니 다.
std::atomic data;
std::atomic data_ready(false);
// a
void writer_thread()
{
data.store(10,std::memory_order_relaxed); // #1: data
data_ready.store(true, std::memory_order_release); // #2: data_ready
}
// b
void reader_thread()
{
while (!data_ready.load(std::memory_order_acquire)) {} // #3: data_ready
std::cout << "data is "<< data.load(std::memory_order_relaxed) << "
"; // #4: data
}
int main() {
std::thread b(writer_thread);
std::thread a(reader_thread);
a.join();
b.join();
system("pause");
}
std::memory_order_consume
때로는 석방 순서 도 엄격 하 다 고 생각 할 때 가 있 습 니 다.저 는 단지 보증 하고 싶 을 뿐 입 니 다.order_consume
std::atomic data;
std::atomic data_ready(false);
// a
void writer_thread()
{
data_ready.store(true, std::memory_order_relaxed); // #2: data_ready
data.store(10, std::memory_order_relaxed); // #1: data
}
// b
void reader_thread()
{
while (!data_ready.load(std::memory_order_consume)) {} // #3: data_ready
std::cout << "data is "<< data.load(std::memory_order_relaxed) << "
"; // #4: data
}
int main() {
std::thread b(writer_thread);
std::thread a(reader_thread);
a.join();
b.join();
system("pause");
}
마지막 으로 여기 잘 한 편 이 있 습 니 다.전재 해 주세요.
https://www.zhihu.com/question/24301047/answer/85844428
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
hdu 1717 소수 화 점수 2 (수학)소수 화 점수 2 레이 는 수학 시간 에 선생님 의 말씀 을 듣 고 모든 소수 가 점수 로 표시 되 는 형식 이 라 고 말 했다. 그 는 녹 기 시 작 했 고 곧 완성 되 었 다. 그러나 그 는 또 하나의 문 제 를...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.