제 질문을 쉽게 설명 할 수있는 방법은 코드에서 설명하는 것입니다. C에서 인과 관계된 예를 들어 답안에 관심을 쏟습니다.복잡한 C11 원자 유형 및 비 원자 읽기 최적화에 대한 부분 업데이트
// Just some complex user defined type
typedef struct {
...
} state_t;
typedef struct {
state_t states[16];
} state_list_t;
static _Atomic state_list_t s_stateList;
// For non-atomic reads
static state_t * const s_pCurrent = &s_stateList.states[0];
// Called from external threads
void get_state(state_list_t * pStateList)
{
*pStateList = atomic_load(&s_stateList);
}
// Only called by 'this' thread
static void update_state(struct state_data_t const * pData)
{
state_list_t stateList = atomic_load(&s_stateList);
for (int i = 0; i < 16; i++)
{
// Do some updating on the data
do_transition(&stateList[i], pData);
}
atomic_store(&s_stateList, stateList);
}
// Only called by 'this' thread
static void apply_state(state_t const * pState)
{
atomic_store(&s_stateList[0], *pState);
}
// Only called by this thread
static bool check_state()
{
// Check (read) some values in the current state
return isOkay(s_pCurrent);
}
첫째, 즉 하나 개의 스레드가 읽고 처음 두 기능은 C11의 아토의 꽤 똑바로 앞으로 사용됩니다
내 구문 오류에 대한 사과, 그러나 이것은 걸쳐 요점을 파악해야한다 ...하는 다른 사람이 쓰는 가치. 내 구체적인 질문은 실제로 마지막 두 함수, apply_state 및 check_state에 관한 것이며, 실제로 이러한 것이 올바른지 여부에 달려있다.
apply_state에서 구조의 일부를 원자 적으로, 특히 배열의 첫 번째 요소 만 업데이트한다는 것을 알 수 있습니다. 본질적으로 _Atomic s_stateList의 모든 요소는 원자 (원자 번호)로 간주되므로 컴파일러는 atomic_store 호출로 문제가 없지만 다른 스레드가 '원자 적으로'읽는 동안 발생할 수 있습니다 (즉 get_state) 또는 각 호출에서 동일한 뮤텍스를 잠금/잠금 해제 과 본질적으로 동등한 동기화입니까? 나는 이것이 기본적으로 다른 변수이기 때문에 가능하다는 것을 알 수 있었다. (물론, 같은 주소이지만, 내가 상태 [1]을 사용했다면?) 그것은 다른 뮤텍스가 사용되게 할 수있다. 또한 state_t가 잠금이없는 경우 어떻게됩니까?
check_state 함수는 동일한 스레드에서만 수정되는 개체에 대해서만 읽기를 수행하기 때문에 여기에서해야 할 일은 괜찮습니다.하지만 필자는 누락 된 부분이 있는지 궁금합니다. 여기 뭐든지. 난 그냥 최근에 원자 변수에 직접 액세스 (할당 또는 함수 인수를 통해) atomic_load() 또는 atomic_store(), 그래서 비 원자 읽기에 대한 개인 참조를 유지하는 경우 궁금하네요 같은 호출을 처리하는 것으로 나타났습니다 가치있는 최적화 또는 컴파일러가 똑같은 최적화를 수행하기에 충분히 영리한 경우입니다.
편집 : 원자 값에 대한 비 원자 포인터를 역 참조 할 때 결과는 정의되지 않습니다.
'static state_t * const s_pCurrent = & s_stateList [0];'제약 조건 위반입니다.포인터는 호환되지 않을뿐만 아니라 원자 유형을 가리키는 비 원자 포인터입니다. – 2501
어쨌든 구문이 정확할 때 고정 된 비 원자 포인터 (다른 올바른 형식의 포인터)에 원자 값 참조를 할당하면 컴파일러로부터 불만이 없습니다. –
컴파일러는 언어를 지정하지 않으므로 진실의 소스로 사용하면 안됩니다. 6.5.16.1 §1의 세 번째 단락에서 * 왼쪽에있는 을 가리키는 유형은 해당 유형의 모든 한정자가 오른쪽에 있음을 나타냅니다. * 따라서 왼쪽 포인터는 오른쪽 포인터가 수행하는 모든 한정자를 가져야합니다. – 2501