C/C++ 기본형은 원자형입니까?
C/C++는 다음과 같은 기본 유형입니까?int
,double
원자, 예를 들어 스레드세이프?
데이터 레이스에서 자유롭습니까?즉, 한 스레드는 이러한 유형의 오브젝트에 쓰고 다른 스레드는 그 오브젝트에서 읽는 경우 동작이 명확하게 정의되어 있습니까?
그렇지 않은 경우 컴파일러에 따라 달라집니까?
원자란 무엇인가?
원자, 원자의 성질을 가지고 무언가를 묘사하는 것입니다.atom이라는 단어는 "분할되지 않은"을 뜻하는 라틴어 atomus에서 유래했다.
통상, 나는 (언어에 관계없이) 원자 조작을 2개의 자질을 가지는 것으로 생각한다.
원자 작전은 항상 분할되지 않는다.
즉, 분리할 수 없는 방식으로 수행되며, OP가 말하는 "스레드세이프"가 바로 이것이라고 생각합니다.어떤 의미에서는 다른 스레드로 볼 때 작업이 즉시 수행됩니다.
예를 들어, 다음의 조작은 분할되어 있을 가능성이 있습니다(컴파일러/하드웨어에 의존합니다).
i += 1;
다른 스레드(가상 하드웨어 및 컴파일러)에 의해 다음과 같이 인식될 수 있기 때문입니다.
load r1, i;
addi r1, #1;
store i, r1;
위의 작업을 수행하는 두 개의 스레드i += 1
적절한 동기화가 이루어지지 않을 경우 잘못된 결과가 발생할 수 있습니다.말합니다i=0
처음에 스레드T1
로드T1.r1 = 0
, 및 스레드T2
로드t2.r1 = 0
양쪽 스레드가 각각 증가합니다.r1
s를 1씩 한 후 결과를 저장합니다.i
두 가지 증분이 수행되었지만, 이 값은i
증가 연산은 분할할 수 있었기 때문에 아직1에 불과합니다이전과 이후에 동기화가 있었다는 점에 유의하십시오.i+=1
다른 스레드는 작업이 완료될 때까지 기다렸을 것이고 따라서 분할되지 않은 동작을 관찰했을 것입니다.
간단한 쓰기라도 분할되지 않을 수 있습니다.
i = 3;
store i, #3;
컴파일러와 하드웨어에 따라 달라집니다.예를 들어 주소가i
정렬이 적절하지 않은 경우 정렬되지 않은 로드/스토어를 사용해야 합니다.이 로드/스토어는 CPU에 의해 여러 개의 작은 로드/스토어로 실행됩니다.
원자 연산은 메모리 순서 시멘틱스를 보증합니다.
비원자 연산은 순서를 변경할 수 있으며 프로그램 소스 코드에 기재된 순서로 발생할 필요는 없습니다.
예를 들어, "as-if" 규칙에서는 프로그램이 지정한 순서에 따라 모든 휘발성 메모리에 대한 액세스가 발생하는 한 컴파일러는 적합하다고 판단되는 대로 저장 및 로드의 순서를 변경할 수 있습니다.따라서 비원자적 운영은 멀티 스레드 프로그램에서의 실행 순서에 대한 가정을 깨고 재정렬될 수 있다.이게 바로 무고한 것처럼 보이는 생선의 사용이int
다중 주파수 프로그래밍의 시그널링 변수가 깨지기 때문에, 비록 쓰기와 읽기가 분리될 수 없을지라도, 그 순서는 컴파일러에 따라 프로그램을 깨질 수 있습니다.원자 연산은 지정된 메모리 시멘틱스에 따라 주변 연산의 순서를 강제합니다.를 참조해 주세요.
또한 CPU는 해당 CPU의 메모리 주문 제약에 따라 메모리 액세스의 순서를 변경할 수도 있습니다.x86 아키텍처의 메모리 주문 제약은 2212 페이지의 인텔 64 / IA32 아키텍처 소프트웨어 개발자 매뉴얼 섹션 8.2에서 확인할 수 있습니다.
프리미티브 타입(int
,char
etc)는 Atomic이 아닙니다.
왜냐하면 특정 조건 하에서는 저장 및 적재 명령 또는 일부 산술 명령이 분리되지 않을 수 있지만 저장 및 적재 순서를 보장하지 않기 때문입니다.따라서 멀티 스레드컨텍스트에서는 다른 스레드에 의해 감시되는 메모리 상태가 그 시점에서 생각되는 상태임을 보증하기 위해 적절한 동기화가 이루어지지 않으면 안전하지 않습니다.
나는 이것이 왜 원시형이 원자형이 아닌지 설명해주길 바란다.
지금까지 다른 답변에서는 볼 수 없었던 추가 정보:
사용하시는 경우std::atomic<bool>
예를 들어, 및bool
는 실제로 타겟아키텍처 상에서 원자성이므로 컴파일러는 장황한 펜스나 잠금을 생성하지 않습니다.플레인 코드와 동일한 코드가 생성됩니다.bool
.
즉,std::atomic
플랫폼에서의 수정이 실제로 필요한 경우에만 코드 효율이 떨어집니다.그래서 피할 이유가 없다.
아니요, 기본 데이터 유형(예:int
,double
)는 아토믹이 아닙니다.를 참조해 주십시오.
대신,std::atomic<int>
또는std::atomic<double>
.
주의: std::atomic
C++11에서 도입되었습니다.C++11 이전에는 C++ 규격에서는 멀티스레딩의 존재를 전혀 인식하지 않았던 것으로 알고 있습니다.
@Josh가 지적한 바와 같이 원자 부울 타입입니다.Rock-free가 보증됩니다.std::atomic
전문화
인용된 문서는 http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4567.pdf 에서 입수할 수 있습니다.표준 규격은 무료가 아니므로 최종/공식 버전이 아닙니다.
1.10 멀티 스레드 실행 및 데이터 레이스
- 한쪽이 메모리 위치(1.7)를 변경하고 다른 한쪽이 같은 메모리 위치를 읽거나 변경하면 두 식 평가가 충돌합니다.
- 라이브러리는 동기 조작으로 특별히 식별되는 다수의 원자 조작(Clause 29)과 뮤텍스 조작(Clause 30)을 정의합니다.이러한 작업은 한 스레드의 할당을 다른 스레드에 표시하는 데 특별한 역할을 합니다.하나 이상의 메모리 위치에서의 동기 동작은 소비 동작, 취득 동작, 해제 동작 또는 취득 동작과 해제 동작의 어느 쪽인가이다.관련된 메모리 위치가 없는 동기 동작은 펜스이며, 취득 펜스, 릴리스 펜스 또는 취득 펜스 또는 취득 펜스와 릴리스 펜스 중 하나가 될 수 있다.또, 동기 조작이 아닌 완화된 아토믹 조작과 특수한 특성을 가지는 아토믹 읽기-수정-쓰기 조작이 있습니다.
- 다음과 같은 경우 두 가지 작업이 동시에 수행될 수 있습니다.
(23.1) - 다른 스레드에 의해 실행됩니다.
(23.2) - 시퀀스되지 않고 적어도1개는 신호 핸들러에 의해 실행됩니다.
프로그램 실행에는 데이터 레이스가 포함되어 있습니다.이것들 중 적어도 하나는 원자적이지 않고 다음에 설명된 신호 핸들러의 특수한 경우를 제외하고 다른 것 이전에 발생하지 않는2개의 잠재적인 충돌 액션이 포함되어 있는 경우입니다.이러한 데이터 경합은 정의되지 않은 동작을 초래합니다.
29.5 원자형
- 적분형 "char"에 대한 원자 템플릿의 명시적 전문화가 있어야 한다.
signed char
,unsigned char
,short
,unsigned short
,int
,unsigned int
,long
,unsigned long
,long long
,unsigned long long
,char16_
t,char32_t
,wchar_t
헤더 내의 typedef에 필요한 기타 유형<cstdint>
적분형 적분별로 전문화atomic<integral>
에, 적분 타입에 적절한 추가 원자 연산을 나타냅니다.전문화가 있어야 한다.atomic<bool>
29.6.1에 규정된 일반 원자 연산을 제공합니다.
- 원자 클래스 템플릿의 포인터 부분 분화가 있어야 한다.이러한 전문화는 표준 레이아웃, 일반 기본 생성자 및 일반 소멸자를 가져야 한다.이들은 각각 집약 초기화 구문을 지원해야 한다.
29.7 플래그 종류 및 조작
- atomic_flag 타입의 객체에 대한 동작은 잠금이 없어야 한다.[주의:그 때문에, 조작도 주소 자유로 할 필요가 있습니다.다른 타입은 잠금프리 조작을 필요로 하지 않기 때문에 atomic_flag 타입은 이 국제규격에 준거하기 위해 필요한 최소한의 하드웨어 실장 타입입니다.나머지 유형은 atomic_flag로 에뮬레이트할 수 있지만 이상적인 속성은 아닙니다.- 종료 노트 ]
C는 태그에 포함되어 있지 않지만 질문에는 (현재) 기재되어 있기 때문에 C 표준에는 다음과 같이 기재되어 있습니다.
5.1.2.3 프로그램 실행
...
추상기계의 처리가 신호 수신에 의해 중단되었을 때 잠기지 않는 원자 객체도 유형도 아닌 객체의 값
volatile sig_atomic_t
부동소수점 환경 상태와 마찬가지로 미지정입니다.핸들러에 의해 수정된 모든 객체의 값(잠금 없는 원자성 객체도 유형도 아님)volatile sig_atomic_t
는 핸들러가 종료되면 부정하게 됩니다.또, 핸들러에 의해서 변경되어 원래의 상태로 복원되지 않은 부동 소수점 환경의 상태도 부정하게 됩니다.
그리고.
5.1.2.4 멀티 스레드 실행 및 데이터 레이스
...
한쪽이 메모리 위치를 수정하고 다른 한쪽이 동일한 메모리 위치를 읽거나 수정하면 두 식 평가가 충돌합니다.
[표준 페이지 추가 - 원자 유형을 명시적으로 다루는 일부 단락]
프로그램 실행에는 서로 다른 스레드에 충돌하는 두 가지 액션이 포함되어 있는 경우 데이터 레이스가 포함됩니다.이 중 적어도 하나는 원자적이지 않고 다른 것 전에 발생하지 않습니다.이러한 데이터 경합은 정의되지 않은 동작을 초래합니다.
신호가 처리를 중단하는 경우 값은 "확정되지 않음"이며 명시적으로 원자적이지 않은 유형에 대한 동시 액세스는 정의되지 않은 동작입니다.
언급URL : https://stackoverflow.com/questions/35226128/are-c-c-fundamental-types-atomic
'programing' 카테고리의 다른 글
vuex를 사용하는 vue/axios에서 글로벌 http 응답 오류 처리 (0) | 2022.07.17 |
---|---|
C에서 파일을 잘라내는 방법 (0) | 2022.07.17 |
VueJs의 구성 요소에 개체 또는 개체 키 전달 (0) | 2022.07.17 |
Java8 lamda를 사용하여 스트림을 역순으로 정렬하려면 어떻게 해야 합니까? (0) | 2022.07.17 |
Java 8 스트림을 어레이로 변환하는 방법 (0) | 2022.07.17 |