2013-06-01 4 views
34
나는 앤서니 윌리엄스 ' "액션 C++ 동시성'을 통해 새로운 멀티 스레딩 인식 메모리 모델과 원자 작업에 대해 이야기 제 5 장에서 읽고있다

, 그는 말한다 : 대한 std::atomic<UDT>를 사용하려면std :: atomic <std::string>이 적절하게 작동합니까?

일부 사용자 정의 UDT의 경우이 유형은 번자 복사 할당 연산자가 있어야합니다.

std::is_trivially_copyable<UDT>::value 

이 논리에 의해, 우리는 std::atomic에 대한 템플릿 인수로 std::string을 사용할 수 없게한다 : 나는 그것을 알고있는 것처럼

,이 사실 다음 반환하는 경우 우리가 std::atomic<UDT>를 사용할 수 있다는 것을 의미한다 제대로 작동하도록하십시오.

그러나, 다음 코드는 컴파일 및 예상 출력을 실행합니다

#include <atomic> 
#include <thread> 
#include <iostream> 
#include <string> 

int main() 
{ 
    std::atomic<std::string> atomicString; 

    atomicString.store("TestString1"); 

    std::cout << atomicString.load() << std::endl; 

    atomicString.store("TestString2"); 

    std::cout << atomicString.load() << std::endl; 

    return 0; 
} 

이 그냥 예상대로 작동하는 일이 정의되지 않은 동작의 경우인가?

미리 감사드립니다.

+1

컴파일러 (및 stdlib 구현)는 무엇입니까? 나는 그것을 컴파일러 [여기] (http://coliru.stacked-crooked.com/view?id=0ce3b66093e9a0a59d5179429373eea7-e54ee7a04e4b807da0930236d4cc94dc)로 만들 수 없었고, 실제로 그것이 내가 기대하고 있었던 것이다. –

+0

@AndyProwl 나는 VS 2012를 사용하고있다. 11 월 CTP없이. –

+2

당신이 그것을 사용함에 따라, 나는 문제를 기대하지 않을 것입니다. 두 개 이상의 스레드가 같은 문자열을 동시에 수정하려고 할 때 문제가 발생합니다. 그 시점에서'string'의 중요한 연산자는 문제를 일으키기 시작할 것입니다. 'std :: atomic'에서 무언가를 래핑하는 것만으로도 코드 없이는 괜찮은 코드를 깨뜨리지 않을 것입니다. 동시에 규칙을 따르지 않아도 코드가 없으면 깨지는 코드는 도움이되지 않습니다. –

답변

38

표준은 std::atomic<std::string>의 특수화를 지정하지 않으므로 일반 template <typename T> std::atomic<T>이 적용됩니다. 29.5 [atomics.types.generic] p1 상태 :

원자적인 제네릭 템플릿이 있습니다. 템플릿 인자 T의 타입은 쉽게 복사 가능해야한다 (3.9).

구현시이 요구 사항의 위반 사항을 진단해야한다는 진술은 없습니다. 그러므로 (a) std::atomic<std::string>을 사용하면 정의되지 않은 동작이 호출되거나, (b) 구현시 일치하는 확장자로 std::atomic<std::string>이 제공됩니다. std::atomic<T> (http://msdn.microsoft.com/en-us/library/vstudio/hh874651.aspx)에 대한 MSDN 페이지를 보면

는 명시 적으로 하찮게 복사 가능한 일 T 요구 사항을 언급 않으며, 그것은 std::atomic<std::string>에 대한 특정 아무 말도하지 않습니다. 확장 인 경우 문서화되지 않았습니다. 내 돈은 정의되지 않은 행동입니다.

구체적 17.6.4.8/1은 (with thanks to Daniel Krügler for setting me straight) 적용 특정한 경우 (여분의 함수 핸들러 함수, 표준 라이브러리 템플릿 컴포넌트 인스턴스를 사용 유형에 동작)에서

상기 C는 ++ 표준 라이브러리에 의존 C++ 프로그램에서 제공하는 구성 요소. 이러한 구성 요소가 요구 사항을 충족시키지 못하면 표준은 구현에 대한 요구 사항을 두지 않습니다.

std::string

확실히 템플릿 매개 변수 T이 하찮게 복사 가능한 할 것을 std::atomic<T> 요구 사항 때문에 표준 장소 구현에 아무런 요구 사항을 충족하지 않습니다. 구현 품질의 문제로, static_assert(std::is_trivially_copyable<T>::value, "std::atomic<T> requires T to be trivially copyable");은이 위반 사항을 쉽게 알아낼 수 있다는 점에 유의하십시오.


2016년 4월 19일 업데이트 : 변화가 일어 났을 때 잘 모르겠지만, VS2015 업데이트 2는 이제 std::atomic<std::string>를 진단 않습니다

error C2338: atomic requires T to be trivially copyable.
0

을이 뜻을 생각하는 이유 std::atomic<std::string>을 읽고 쓰려고하는 여러 스레드가있을 때 '올바르게'작동합니까?

이것은 C++입니다. 발에서 몸을 쏠 수밖에 없습니다. 당신이 자유롭게 사용할 수있는 요구 사항을 만족시키지 못하는 타입을 사용하고자한다면, 컴파일러는 당신을 멈추게 할 수도 있지만, 여러 스레드가 읽으려고 할 때 어떤 시점에서 이상한/설명 할 수없는 행동을 보게 될 것입니다/문자열을 씁니다.

이 요구 사항은 객체가 쉽게 복사 가능하지 않으면이 장면을 시각화하는 경우 읽기 및 쓰기의 원 자성을 보장하기위한 것입니다. 문자열에 "이전 값"이있었습니다. 1 Writer가 .store ("New Data")를 발행하면 같은 변수에 .load()를 발행하는 다른 스레드가 생기고 이제 trivially_copyable 속성이 없으면 판독기 스레드는 "Nld Value"또는 "New Value"등을 볼 수 있습니다. 원자 적으로 업데이트 할 수 없으므로 이상한 결과가 발생합니다.

게시 한 예가 순차적 코드이므로이 문제가 발생하지 않습니다.

6

아니요, 이것은 정의되지 않은 동작입니다. 표준 : : 문자열이 하찮게 복사 가능한하지 않기 때문에 또한, 준수 컴파일러가 발행해야 "적어도 하나의 진단 메시지"

29.5 원자 유형

원자 일반적인 클래스 템플릿이 있습니다

. 템플릿 인자 T의 타입은 쉽게 복사 가능해야한다 (3.9).

1.4 구현을 준수

- 프로그램이 어떤 진단이 규칙의 위반이 포함 된 경우 [...] 순응 구현은 적어도 하나의 진단 메시지를 발급한다.

관련 문제