3

현재 유효한 C++을 읽고 있습니다. 정적 로컬 변수 사용에 관한 절이 있으며, 여러 스레드가 정적 변수에 액세스하는 경우 해당 변수를 초기화하는 동안 경쟁 조건이있을 수 있습니다.정적 로컬 변수의 경쟁 조건

적어도 내 해석입니다. 사실입니까? 예를 들어 C#에서는 클래스 정적 변수를 초기화해도 경쟁 조건이 발생하지 않습니다.

예를 들어,이 코드는 정적 변수 초기화 중에 경쟁 상태가 될 수 있습니까?

FileSystem& tfs() 
{ 
    static FileSystem fs; 
    return fs; 
} 

다음은 본 설명서를 제외한 부분입니다.

class FileSystem { ... }; // as before 

FileSystem& tfs() // this replaces the tfs object; it could static in the FileSystem class 
{ 
    static FileSystem fs; // define and initialize a local static object 
    return fs; // return a reference to it 
} 

:

는 여기에 모두 TFS와 TEMPDIR에 적용되는 기술이다. 그들은 지금 tfs() 참조 대신 tfstempDirtempDir()를 제외하고이 수정 된 시스템 프로그램의

class Directory { ... }; // as before 

Directory::Directory(params) // as before, except references to tfs are now to tfs() 
{ 
... 
std::size_t disks = tfs().numDisks(); 
... 
} 

Directory& tempDir() // this replaces the tempDir object; it could be static in the Directory class 
{ 
    static Directory td; // define/initialize local static object 
    return td; // return reference to it 
} 

클라이언트는 그들에 을 사용 그대로. 즉, 객체 자체를 사용하는 대신 객체 에 대한 참조를 반환하는 함수를 사용합니다. 이 제도에 의해 결정

참조 - 리턴하는 함수는 항상 간단하다 : 그들은 '특히, 정의 및 라인 1의 로컬 정적 객체를 초기화, 라인 2.이 단순 인라인 그들을 훌륭한 후보를 만들어에 에게 반환 자주 호출됩니다 (항목 30 참조). 에서 이러한 함수에 정적 객체 이 포함되어 있다는 사실은 다중 스레드 시스템에서 문제가되는 것입니다. 다시 말해, non-const 정적 개체 (로컬 또는 로컬이 아닌)의 모든 종류 은 복수 스레드가있는 상태에서 이 대기하도록하는 데 문제가 있습니다. 문제를 해결하는 한 가지 방법은 프로그램의 단일 스레드 시작 부분에서 모든 참조를 반환하는 모든 함수를 수동으로 호출하는 것입니다. 이렇게하면 초기화와 관련된 경쟁 조건이 제거됩니다.

+0

https://blogs.msdn.microsoft.com/oldnewthing/20040308-00/?p=40363 –

답변

8

이 섹션은 구식입니다. C++ 03 표준에는 스레드에 대한 언급이 없었으므로 C++ 구현시이를 추가 할 때 언어 구조의 스레드 안전성과 관련하여 원하는대로 수행했습니다. 일반적인 선택은 정적 로컬 변수의 스레드 안전성 초기화를 보장하지 않는 것입니다.

: C++ 11에서

는 지역 정적 변수는 정확히 한 번만 프로그램의 제어 흐름이 여러 스레드 6.7/4에서 동시에 발생하는 경우에도, 자신의 선언을 통해 전달하는 첫 번째 시간을 초기화 할 보장 구현시 네임 스페이스 범위 (3.6.2)에서 정적 또는 스레드 저장 기간을 사용하여 변수를 정적으로 초기화 할 수있는 것과 동일한 조건에서 정적 또는 스레드 저장 기간을 사용하여 다른 블록 범위 변수를 조기에 초기화 할 수 있습니다. 그렇지 않으면 이러한 변수는 처음 제어가 선언을 통과 할 때 초기화됩니다. 그러한 변수는 초기화 완료시 초기화 된 것으로 간주됩니다.예외를 throw하여 초기화가 끝나면 초기화가 완료되지 않으므로 다음에 컨트롤이 선언에 들어갈 때 다시 시도됩니다. 변수가 초기화되는 동안 컨트롤이 동시에 선언에 들어가면 동시 실행은 초기화가 완료 될 때까지 대기합니다.

그렇다고해도 초기화 만 안전합니다. 반환 된 FileSystem을 여러 스레드에서 동시에 사용할 계획이면 FileSystem 자체가 스레드 안전 작동을 제공해야합니다.