> 백엔드 개발 > Golang > 이 고루틴 코드가 예상치 못한 결과를 생성하는 이유는 무엇이며 데이터 경합을 어떻게 피할 수 있습니까?

이 고루틴 코드가 예상치 못한 결과를 생성하는 이유는 무엇이며 데이터 경합을 어떻게 피할 수 있습니까?

Linda Hamilton
풀어 주다: 2024-12-11 18:36:12
원래의
485명이 탐색했습니다.

Why Does This Goroutine Code Produce Unexpected Results and How Can Data Races Be Avoided?

고루틴 동작의 데이터 경합

제공된 코드 조각은 예측할 수 없는 결과를 초래할 수 있는 데이터 경합 문제를 소개합니다. 핵심 문제는 고루틴의 특성과 범위 변수가 고루틴 함수에 전달되는 방식에서 비롯됩니다.

데이터 경쟁

제공된 코드는 범위를 사용합니다. 데이터 슬라이스를 반복하고, 각 반복마다 필드 구조체의 이름 필드를 인쇄하기 위해 새로운 고루틴을 시작합니다. 그러나 각 반복 내에서 범위 변수 v는 참조인 데이터 슬라이스의 동일한 기본 데이터 구조를 가리킵니다.

루프가 진행되고 변수 v가 ​​데이터 슬라이스를 반복함에 따라 해당 값은 다음과 같이 변경됩니다. 다음 요소를 가리킵니다. 이는 고루틴의 함수가 실행될 때 슬라이스의 마지막 요소인 v의 마지막 값을 갖게 된다는 것을 의미합니다.

따라서 고루틴을 실행하면 다음의 이름 필드가 인쇄됩니다. 의도한 "하나", "둘", "셋" 대신 마지막 요소인 "셋"만 세 번 사용합니다. 주문하세요.

솔루션

이 문제를 해결하려면 다음과 같은 여러 가지 솔루션을 사용할 수 있습니다.

  1. 새 변수 생성 :

    • 새로운 변수 v를 소개합니다 해당 반복으로만 범위가 지정된 루프 반복 내에서. 이렇게 하면 각 고루틴이 슬라이스의 올바른 요소를 가리키는 고유한 v 버전을 갖게 됩니다.
  2. 포인터 슬라이스 사용:

    • 직접 참조 대신 필드 구조체에 대한 포인터를 유지하도록 데이터 슬라이스를 수정하세요. 이런 식으로 루프의 각 반복은 특정 요소에 대한 포인터를 가져와 변수 덮어쓰기 문제를 제거합니다.
  3. 슬라이스 요소의 주소 사용:

    • 범위 루프 중에 슬라이스 요소의 주소를 명시적으로 가져옵니다. 이는 각 고루틴에 슬라이스의 특정 요소에 대한 올바른 주소를 제공합니다.

추가 접근 방식

  • 익명 함수에 인수 전달: 고루틴 내에서 익명 함수를 사용하여 범위 변수를 인수로 전달합니다. 이렇게 하면 각 고루틴이 범위 변수의 고유한 복사본에 액세스할 수 있습니다.
  • 포인터 수신기: 코드는 구조체 메서드(field.print()를 사용합니다. ) 포인터 수신기가 있습니다. 이 구현에서는 일반적으로 문제를 방지하기 위해 데이터 슬라이스에 대한 포인터 슬라이스 사용을 보장합니다.

위 내용은 이 고루틴 코드가 예상치 못한 결과를 생성하는 이유는 무엇이며 데이터 경합을 어떻게 피할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿