문제

상당히 기본적인 질문이지만 어디서나 묻는 것을 보지 못합니다.

우리는 다음과 같은 글로벌 구조물 (C)을 가지고 있다고 가정 해 봅시다.

struct foo {
  int written_frequently1;
  int read_only;
  int written_frequently2;
};

우리가 많은 스레드를 읽고 쓰고 쓰기가 있다면, 우리는 written_frequently 우리는이 구조물에 대한 과제가 원자력이 될 것이라고 확신 할 수 없기 때문에 읽기에도 회원들도 읽습니다.

우리가 많은 스레드를 읽으려면 read_only 멤버, 그리고 글을 쓸 수 없다.

(나는 거절하는 경향이 있습니다. 직전과 후에 위치가 끊임없이 변경되었다는 사실은 read_only 멤버 및 값을 읽는 여러 스레드가 서로 방해해서는 안됩니다. 하지만 확실하지 않습니다.)


편집 : 나는 지금이 질문을 훨씬 더 잘 물었을 것임을 알고 있습니다. 매우 구체적으로 내가 의미하는 바. 당연히, 나는 처음 질문을했을 때 관련된 모든 문제를 실제로 맥주하지 않았습니다. 물론, 지금 질문을 종합적으로 편집한다면, 나는이 위대한 답을 모두 망칠 것입니다. 내가 의미하는 바는 다음과 같습니다.

struct bar {
  char written_frequently1[LONGISH_LEN];
  char read_only[LONGISH_LEN];
  char written_frequently2[LONGISH_LEN];
};

내가 요청한 주요 문제는이 데이터가 구조물의 일부이기 때문에 다른 구조물 멤버의 영향을 받고 있으며, 그 대가로 영향을 줄 수 있습니까?

회원들이 ints이고, 따라서 글이 원자 일 가능성이 높다는 사실은 실제로이 경우에 빨간 청어 일뿐입니다.

도움이 되었습니까?

해결책 10

모든 위대한 대답자들에게 감사드립니다 (그리고 모든 위대한 답변).

요약 :

구조물의 읽기 전용 멤버가있는 경우 (우리의 경우, 값이 한 번 설정되면 스레드가 읽기 오래 전에 설정되면이 멤버를 읽는 스레드는 잠금, 뮤트, 세마포어 등이 필요하지 않습니다. 다른 동시성 보호.

다른 회원이 자주 작성 되더라도 마찬가지입니다. 다른 변수가 모두 동일한 구조물의 일부라는 사실은 아무런 차이가 없습니다.

다른 팁

작업이 원자임을 보장하려면 뮤트가 필요합니다. 이 특별한 경우에는 당신입니다 뮤텍스가 전혀 필요하지 않을 수 있습니다. 구체적으로, 각 스레드가 작성하는 경우 하나 요소 그리고 쓰기는 원자입니다 그리고 새 값은 현재 값과 무관합니다. 어느 요소 (자체 포함), 문제가 없습니다.

예시: 여러 스레드 각각은 "last_updated_by"변수를 업데이트하여 최종 스레드를 업데이트 한 마지막 스레드를 업데이트합니다. 분명히 변수 자체가 원자 적으로 업데이트되는 한 오류가 발생하지 않습니다.


그러나 당신은 하다 스레드 인 경우 일관성을 보장하려면 뮤트가 필요합니다 읽거나 씁니다 한 번에 하나 이상의 요소, 특히 잠금을 언급하기 때문에 요소 대신 전체 구조.

예시: 스레드는 구조의 "Day", "Month"및 "Year"요소를 업데이트합니다. 이것은 원자 적으로 발생해야합니다. 다른 스레드는 "달"증가 후 구조를 읽지 않도록하지만 "날"이 1으로 랩되기 전에 2 월 31 일과 같은 날짜를 피하십시오. 명예 읽을 때의 뮤트; 그렇지 않으면 잘못된 반 업데이트 된 값을 읽을 수 있습니다.

read_only 멤버가 실제로 읽는 경우 데이터가 변경 될 위험이 없으므로 동기화가 필요하지 않습니다. 스레드가 시작되기 전에 설정된 데이터 일 수 있습니다.

주파수에 관계없이 작성할 수있는 모든 데이터에 대해 동기화를 원합니다.

변수가 초기화 될 때 적어도 한 번에 기록되기 때문에 "읽기 전용"은 약간 오해의 소지가 있습니다. 이 경우 초기 쓰기와 후속 읽기 사이에 다른 스레드에있는 경우에도 메모리 장벽이 필요하거나 이기지가없는 값을 볼 수 있습니다.

독자들도 뮤텍스가 필요합니다!

뮤텍스가 작가에만 해당되고 독자가 필요하지 않다는 일반적인 오해가있는 것 같습니다. 이것은 잘못된 것입니다. 그리고이 오해는 버그에 책임이 있습니다 진단하기가 매우 어렵습니다.

예제의 형태로 이유는 다음과 같습니다.

코드로 매 초마다 업데이트되는 시계를 상상해보십시오.

if (++seconds > 59) {        // Was the time hh:mm:59?
   seconds = 0;              // Wrap seconds..
   if (++minutes > 59)  {    // ..and increment minutes.  Was it hh:59:59?
     minutes = 0;            // Wrap minutes..
     if (++hours > 23)       // ..and increment hours.  Was it 23:59:59?
        hours = 0;           // Wrap hours.
    }
}

코드가 Mutex에 의해 보호되지 않으면 다른 스레드는 다음을 읽을 수 있습니다. hours, minutes, 그리고 seconds 업데이트가 진행되는 동안 변수가 진행 중입니다. 위의 코드에 따라 :

[Start just before midnight] 23:59:59
[WRITER increments seconds]  23:59:60
[WRITER wraps seconds]       23:59:00
[WRITER increments minutes]  23:60:00
[WRITER wraps minutes]       23:00:00
[WRITER increments hours]    24:00:00
[WRITER wraps hours]         00:00:00

첫 번째 증분에서 최종 작업까지 시간이 유효하지 않습니다. 6 단계 후. 독자 가이 기간 동안 시계를 확인하면 틀릴뿐만 아니라 값이 표시됩니다. 불법적인. 그리고 당신의 코드가 가능하기 때문에 의존하다 없이 시계에 표시 시간 직접, 이것은 추적하기 어려운 "Ricochet"오류의 고전적인 소스입니다.

수정은 간단합니다.

Clock Update 코드를 Mutx로 둘러싸고 있습니다 독자 기능을 만듭니다 저것 또한 뮤텍스를 잠그십시오 실행하는 동안. 이제 독자는 업데이트가 완료 될 때까지 기다릴 것입니다. 작가는 중간 읽기 값을 변경하지 않습니다.

아니.

일반적으로 자원에 대한 동시 접근을 방지하려면 세마포어가 필요합니다 ( int 이 경우). 그러나 이후 read_only 멤버는 읽기 전용이며 액세스 중/중에 변경되지 않습니다. 원자 읽기 일 필요조차 없습니다. 아무것도 변하지 않으면 항상 안전합니다.

어떻게 설정하고 있습니까? read_only 처음에?

모든 스레드가 읽는 경우 단지 세마포어가 필요하지 않습니다.

이 논문 중 하나를 읽는 것을 즐길 수 있습니다. 실용적인 잠금 무료 프로그래밍, 제공된 스 니펫을 해부하고 이해합니다.

나는 함수 호출 뒤에 각 필드를 숨길 것입니다. 쓰기 전용 필드에는 세마포어가 있습니다. 읽기 전용은 값을 반환합니다.

이전 답변에 추가 :

  1. 이 경우 자연 동기화 패러다임은 세마포어가 아닌 상호 배제입니다.
  2. 나는 당신이 readonly 변수에 뮤텍스가 필요하지 않다는 데 동의합니다.
  3. 구조의 읽기 쓰기 부분에 일관성 제약이있는 경우 일반적으로 필요합니다. 하나 뮤텍스 모두 그들 중 작동을 원자력으로 유지하기 위해.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top