다 중 스 레 드 에서 공유 변 수 를 사용 하 는 문제
2824 단어 다 중 스 레 드
하나의 병렬 스 레 드 는 프로 세 스 의 컨 텍스트 에서 실 행 됩 니 다. 모든 스 레 드 는 스 택, 프로그램 카운터, 스 레 드 ID, 조건 코드 등 독립 된 스 레 드 컨 텍스트 가 있 습 니 다. 모든 스 레 드 는 다른 스 레 드 와 함께 이 를 제외 한 프로 세 스 컨 텍스트 의 나머지 부분 을 공유 합 니 다. 전체 사용자 의 가상 주소 공간 을 포함 합 니 다.물론 같은 열 린 파일 의 집합 도 공유 합 니 다.여기 서 주의해 야 할 것 은 레지스터 는 공유 되 지 않 고 가상 메모리 는 항상 공유 된다 는 것 이다.공유 가 있 으 면 공유 변 수 를 조작 하 는 과정 에서 알 수 없 는 값 을 얻 는 것 을 방지 해 야 한다. Linux 커 널 에 원자 유형 과 원자 조작 이라는 개념 이 있다. 사용자 상태 에서 이러한 원자 조작 이 존재 하지 않 기 때문에 우리 사용자 상태 에서 이 공유 변 수 를 조작 하 는 스 레 드 를 동기 화해 야 한다.
동기 화 는 왜 하 는 거 죠?한 프로그램 에 전체 변수 cnct 가 있다 고 가정 하기 때문에 초기 값 은 0 입 니 다. 이어서 우 리 는 두 개의 스 레 드 를 만 들 었 습 니 다. 완 성 된 기능 은 모두 하나의 순환 에서 이 변 수 를 + 1 작업 을 하 는 것 입 니 다. 이 두 스 레 드 작업 이 끝 난 후에 어떤 상황 이 발생 할 지 상상 해 보 세 요.
void *thread(void* value)
{
int max = *((int*)value)
for(int i=0;i<max;i++)
{
cnt++;
}
return NULL;
}
만약 에 우리 가 여기 있 는 max 가 10000 이 라 고 가정 하면 우리 가 얻 고 싶 은 결 과 는 당연히 20000 이지 만 실행 한 후에 결 과 는 우리 가 기대 하 는 20000 이 아니 라 20000 보다 작은 값 이다.왜 이런 현상 이 나 타 났 을 까?여기 가 바로 우리 가 왜 라인 을 동기 화해 야 하 는 지 입 니 다.C 언어의 측면 에서 볼 때 cnct + + 는 하나의 문장 이기 때문에 실제 적 으로 우 리 는 마음속 으로 그것 을 원자 조작 으로 여 긴 다. 사실은 이런 조작 문 구 는 어 셈 블 리 코드 에서 세 단계 로 나 누 어 실행한다.
1) 이 값 을 메모리 에서 꺼 내 레지스터 에 넣 기;
2) 、 레지스터 의 값 을 + 1 조작 하기;
3), 레지스터 의 값 을 메모리 에 넣 습 니 다.
다 중 스 레 드 에 있어 서 우 리 는 언제 어떤 스 레 드 를 실행 할 지 모 르 기 때문에 실행 순 서 는 알 수 없다.우리 가 생각 하 는 것 은 먼저 한쪽 을 집행 하 게 한 후에 다른 쪽 을 집행 하 는 것 이다.지금 우 리 는 이 문 제 를 극단 화 하 는 것 이 좋 습 니 다. 즉, 두 스 레 드 가 교차 하여 실행 하 는 것 입 니 다. 왼쪽 의 실행 스 레 드 가 A 이 고 오른쪽 은 B 라 고 가정 합 니 다. A 가 먼저 실행 한다 고 가정 하면 A 는 메모리 에서 cnct 의 값 을 꺼 냅 니 다. 그러면 현재 R1 에서 의 값 은 0 입 니 다. 이 어 A 스 레 드 는 B 스 레 드 에 의 해 중단 되 고 A 는 실행 을 중단 합 니 다. B 는 메모리 에서 cnct 의 값 을 꺼 냅 니 다. 현재 R2 에서 의 값 도 0 입 니 다.그 다음 에 A 가 수행 할 차례 가 되 고 1 을 더 하면 R1 이 1 이 고 다음 에 B 가 수행 할 차례 가 되 며 1 을 더 하면 R2 가 1 이다.그리고 A 는 값 을 메모리 에 쓰 고 B 도 값 을 메모리 에 쓴다.이번에 우 리 는 메모리 의 값 이 우리 가 기대 하 는 2 가 아니 라 1 이라는 것 을 알 았 다.
그렇다면 어떻게 그것 을 정확 한 집행 순 서 를 진행 시 킬 수 있 습 니까?동기 화, 잠 금 으로 동기 화 작업 을 완성 할 수 있 습 니 다.
for(int i=0;i<max;i++)
{
P(&mutex); //
cnt++;
V(&mutex); //
}
cnct 에 1 을 추가 하 는 작업 을 할 때 이 작업 에 자 물 쇠 를 추가 하 는 것 은 현재 이 스 레 드 만 이 작업 을 수행 하고 있 음 을 의미 합 니 다. 다른 스 레 드 는 모두 밖에서 기 다 려 야 합 니 다. 이 스 레 드 가 잠 겨 야 다른 스 레 드 가 들 어 갈 수 있 습 니 다.자 물 쇠 를 추가 한 후에 우 리 는 위의 그림 의 집행 과정 을 다시 보 겠 습 니 다. 또한 극단 적 인 상황 이 라 고 가정 합 니 다. A 는 먼저 자 물 쇠 를 추가 한 다음 에 그 세 가지 절 차 를 완성 합 니 다 (이때 한 라인 만 조작 할 수 있 는 권한 이 있 기 때 문 입 니 다). 자 물 쇠 를 풀 겠 습 니 다.현재 메모리 의 값 은 1 이 고 A 에 자 물 쇠 를 추가 한 다음 에 똑 같이 세 단 계 를 완성 하고 자 물 쇠 를 풀 수 있 습 니 다.현재 메모리 의 값 은 2 입 니 다.기 대 했 던 것 과 같다.
물론 자 물 쇠 를 넣 는 문제 에 대해 서 는 자물쇠 가 잠 겨 있 는 것 을 막 아야 하 므 로 여 기 는 논의 하지 않 겠 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA 다 중 스 레 드 메커니즘 의 스 레 드 생 성target 을 실행 대상 으로 지정 한 name 을 이름 으로 하고 group 에서 참조 하 는 스 레 드 그룹의 일원 으로 새 Thread 대상 을 할당 합 니 다. 이 스 레 드 가 독립 된 Runnable 실...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.