C ++ 읽기 및 쓰기는 int 원자입니까? 그것을 읽는다. 읽기 및 쓰기 순서가 관련이없는

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

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

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

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

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



답변

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


답변

소년, 무슨 질문입니다. 이에 대한 대답은 다음과 같습니다.

예, 아니요, 음, 상황에 따라 다릅니다.

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

또한 C / C ++를 사용하는 경우 공유 값을 휘발성으로 표시하는 것을 잊지 마십시오. 그렇지 않으면 옵티마이 저는 변수가 스레드 중 하나에서 업데이트되지 않는다고 생각합니다.


답변

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


답변

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

실제로 데이터 유형이 기본 단어 크기보다 크면 잘못된 값을 얻을 수 있습니다. 또한 다른 스레드는 읽기 및 / 또는 쓰기를 이동하는 최적화로 인해 작성된 값을 볼 수 없습니다.


답변

동기화해야하지만 특정 아키텍처에서는이를 수행하는 효율적인 방법이 있습니다.

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

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


답변

Windows에서 Interlocked *** Exchange *** Add는 원 자성이 보장됩니다.


답변

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