IT

C ++ 읽기 및 쓰기는 int 원자입니까?

lottoking 2020. 10. 8. 07:27

C ++ 읽기 및 쓰기는 int 원자입니까?


나는 두 개의 하나는 int를 업데이트하고 다른 하나는 읽는다. 읽기 및 쓰기 순서가 관련이없는 통계 값입니다.

내 질문은 어쨌든이 멀티 바이트 값에 대한 액세스를 동기화해야합니까? 또는 다른 말로하면 쓰기의 일부가 완료되고 중단 된 다음 읽기가 계속 될 수 있습니다.

예를 들어, 0x00010000의 증가 된 값을 가져 오는 값 = 0x0000FFFF를 생각해보세요.

걱정해야 할 값이 0x0001FFFF처럼 보이는 시간이? 확실히 유형이 클수록 이와 같은 일이 더 많이 보관할 수 있습니다.

저는 항상 이러한 유형의 액세스를 동기화했지만 커뮤니티가 어떻게 생각하는지 궁금했습니다.


처음에는 원시 머신 크기의 읽기 및 쓰기 원자 적이라고 생각할 수 있고 프로세서 / 코어 하나의 캐시 일관성을 포함하여 처리해야 할 여러 문제가 있습니다. Windows에서는 Interlocked *, Linux에서는 이에 대한 원자 적 연산을 사용합니다. C ++ 0x는 멋진 크로스 플랫폼 인터페이스로이를 래핑하는 "원자"템플릿을 사용합니다. 지금은 플랫폼 추상화 계층을 사용하는 경우 기능을 제공 할 수 있습니다. ACE 는 클래스 템플릿 ACE_Atomic_Op를 참조하십시오 .


소년, 무슨 질문입니다. 이에 대한 대답은 다음과 가변합니다.

예, 아니요, 음, 상황에 따라 늘어서 있습니다.

그것은 모두 시스템의 아키텍처로 귀결됩니다. IA32에서 정렬 된 주소는 원자 적 연산입니다. 정렬되지 않은 쓰기는 원자적일 수 있고 사용중인 캐싱 시스템에 따라 있습니다. 메모리가 단일 한 L1 캐시에 라인이 있으면 원 자성이고 서열이됩니다. CPU와 RAM 사이의 버스 폭은 원자 적 특성에 영향을 미칠 수 있습니다. 8086에서 정렬 된 16 비트 쓰기는 원자 적이지만 8088에서 쓰기는 8088에 8 비트 버스 만 있었기 때문에 가능성이 있습니다. 16 비트 버스.

또한 C / C ++를 사용하는 경우 공유 값을 인증으로 표시하는 것을 잊지 않습니다. 즉, 표준화 된 옵티마 이어는 변수가 옵티마 이어 업데이트되지 않습니다.


4 바이트 값을 읽고 있고 메모리에서 DWORD로 실행되고 있고 I32 아키텍처에서 실행중인 경우 읽기 및 쓰기가 원자 적입니다.


예, 액세스를 동기화해야합니다. C ++ 0x에서는 데이터 경쟁이며 정의되지 않은 동작입니다. POSIX는 이미 정의되지 않은 동작입니다.

실제로 데이터 유형이 기본 단어 크기보다 크면 잘못된 값을 얻을 수 있습니다. 또한 다른 표기는 읽기 및 / 또는 쓰기에 표기된 값을 볼 수 없습니다.


동기화해야하는 특정 아키텍처에서는 수행하는 방법이 있습니다.

가장 좋은 방법은 조건부로 구현을 플랫폼 별 구현으로 대체 할 수있는 하나의 서브 루틴 (아마 매크로 라우터 마스킹 됨)을 사용하는 것입니다.

Linux에는 이미이 코드 중 일부가 있습니다.


Windows에서 연동 *** Exchange *** 추가가 가능합니다.


모든 사람들이 위층에서 말한 것을 반영하기 위해 C ++ 0x 이전 언어는 여러 가지에서 공유 메모리 액세스에 대해 어떤 것도 보장 할 수 없습니다. 모든 보장은 컴파일러에 달려 있습니다.


아니요, 그렇다고 가정 할 수 없습니다. 하지만이를 원자 적으로 수행하는 몇 가지 트릭이 일반적으로 이식 할 수 없습니다 ( Compare-and-swap 참조 ).


나는 많은 사람들, 특히 Jason에 동의합니다 . Windows에서는 InterlockedAdd와 그 친구들을 사용합니다.


언급 된 한 캐시 문제 외에도 ...

더 작은 프로세서로 코드를 이식하면 더 이상 원 자성이 아닙니다.

IMO, 스레딩 문제는 위험하기에는 너무 까다 롭습니다.


이 예를 들어 보겠습니다.

int x;
x++;
x=x+5;

첫 번째 명령문은 단일 CPU주기를 사용하는 단일 INC 어셈블리 지시문으로 변환되기 때문에 원자 적이라고 가정합니다. 그러나 두 번째 할당에는 여러 작업이 필요하지 않습니다.

또 다른 예,

x=5;

다시 말하지만, 정확히 어떤 일이 발생하는지 확인해야합니다.


tc, 나는 당신이 상수 (6과 같은)를 사용하는 순간, 명령이 한 기계 사이클에서 완료되지 않을 것이라고 생각합니다. x ++와 비교하여 x + = 6의 세트를 확인하십시오.


어떤 사람들은 ++ c가 원자 적이라고 생각하지만 생성 된 어셈블리를 주시합니다. 예를 들어 'gcc -S'사용 :

movl    cpt.1586(%rip), %eax
addl    $1, %eax
movl    %eax, cpt.1586(%rip)

int를 증가시키는 호출 컴파일러는 먼저 그곳에로드하고 메모리에 다시 저장합니다. 이것은 원자 적이 지입니다.


확실히 아니야! 우리의 최고 C ++ 권위자 인 M. Boost :
"보통"국내에 대한 연산이 원 자성이 보장되지는 않습니다.


이식 가능한 유일한 방법은 컴파일러의 signal.h 헤더에 정의 된 sig_atomic_t 유형을 사용하는 것입니다. 대부분의 C 및 C ++ 구현에서는 int입니다. 그런 다음 변수를 "volatile sig_atomic_t"로 선언합니다.

참고 URL : https://stackoverflow.com/questions/54188/are-c-reads-and-writes-of-an-int-atomic