programing

여러 스레드가 동일한 메모리에 액세스하지 않도록 하여 잠금을 방지할 수 있습니까?

showcode 2023. 6. 9. 22:09
반응형

여러 스레드가 동일한 메모리에 액세스하지 않도록 하여 잠금을 방지할 수 있습니까?

예를 들어 배열이 크고 여러 스레드로 내용을 처리하려고 합니다.중복이 없도록 각 스레드를 특정 섹션에 위임하면 스레드가 어레이 외부의 다른 메모리에 액세스하지 않는다고 가정할 때 잠금이 필요하지 않습니까?

다음과 같은 것(의사 코드):

global array[9000000];

do_something(chunk) {
    for (i = chunk.start; i < chunk.end; i++)
        //do something with array
}

main() {
    chunk1 = {start: 0, end: 5000000};
    chunk2 = {start: 5000000, end: 9000000};

    start_thread(thread1, do_something(chunk1));
    start_thread(thread2, do_something(chunk2));

    wait_for_join(thread1);
    wait_for_join(thread2);
    //do something else with the altered array
}

C++11 컴파일러에서 이것은 안전합니다 [intro.memory] (§1.7):

메모리 위치는 스칼라 유형의 개체이거나 0이 아닌 너비를 가진 인접 비트 필드의 최대 시퀀스입니다. [...] 두 개의 실행 스레드(1.10)는 서로 간섭하지 않고 별도의 메모리 위치를 업데이트하고 액세스할 수 있습니다.

C11은 § 3.14에서 동일한 보증(동일한 문구를 사용하기도 함)을 제공합니다.

C++03 컴파일러에서 이것은 표준으로 작동하는 것을 보장하지 않지만 컴파일러가 확장과 유사한 보장을 제공하는 경우에도 작동할 수 있습니다.

예: 두 스레드가 동일한 요소에 액세스하지 않도록 보장할 수 있으면 추가 동기화가 필요하지 않습니다.

두 스레드가 동기화 없이 동일한 메모리 위치에 액세스할 경우(그 중 하나 이상이 수정됨) 충돌(따라서 잠재적인 데이터 경합)만 발생합니다.

(참고: 이 답변은 C++11 메모리 모델을 기반으로 합니다.저는 방금 당신이 제2외국어에 대해서도 질문하고 있다는 것을 알았습니다. 저는 C11이 매우 유사한 메모리 모델을 지정한다고 믿지만, 그 대답이 C에도 유효하다고 확실히 말할 수는 없습니다.두 언어의 이전 버전의 경우 스레드 안전은 구현에 따라 다릅니다.)

네, 물론 가능합니다.

TCMalloc가 좋은 예입니다.

네.

스레드가 동일한 메모리 위치에 액세스하지 않도록 보장할 필요도 없습니다.하나의 스레드가 다른 스레드가 액세스하는 위치를 수정하지 않아야 합니다(읽기 또는 쓰기를 의미하는지에 관계없이).

동시 액세스가 전혀 없거나 읽기 전용 동시 액세스를 사용할 경우 잠금 없이 이동할 수 있습니다.

중요한 성능 문제!

맞습니다. 다른 사람들이 말했듯이 메모리 위치가 공유되지 않기 때문에 명시적인 잠금이 필요하지 않습니다.

그러나 임의 청크로 인해 캐시 라인이 공유될 가능성이 높기 때문에 암묵적인 하드웨어 동기화를 트리거할 수 있습니다(그러나 예제에 사용된 수치와 크게 다르지 않음).잘못된 공유로 알려져 있습니다.

OpenMP와 같은 상위 수준의 접근 방식은 다음과 같은 문제를 해결합니다.

  • 청크 정렬(및 스레드 번호)은 기본 하드웨어에 따라 조정됩니다.
  • 스레드 풀을 보다 효율적으로 제어할 수 있습니다(예: 스레드 인스턴스화 비용 상각).
  • 쓰기는 더 쉽고, 실제로는 덜 거슬립니다.

언급URL : https://stackoverflow.com/questions/20548528/can-you-avoid-locking-by-guaranteeing-that-multiple-threads-wont-access-the-sam

반응형