python 진급 의 다 중 스 레 드 가 같은 전역 변 수 를 처리 하 는 방법
from threading import Thread
global_num = 0
def func1():
global global_num
for i in range(1000000):
global_num += 1
print('---------func1:global_num=%s--------'%global_num)
def func2():
global global_num
for i in range(1000000):
global_num += 1
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)
lock = Lock()
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
출력 결과:
global_num=0
---------func1:global_num=1492752--------
--------fun2:global_num=1515462
\#다 중 스 레 드 가 다 중 프로 세 스 와 같 지 않 기 때문에 모든 프로 세 스 는 하나의 독립 된 자원 블록 입 니 다.스 레 드 사 이 는 주 스 레 드 를 공유 하 는 자원 블록 입 니 다.(이렇게 말 하 는 것 은 적절 하지 않 지만)\#이렇게 하면 스 레 드 간 의 데이터 전달 이 편리 하지만 스 레 드 간 의 실행 순서 가 불확실 하기 때문에 마지막 결 과 는 출력 해 야 할 정확 한 결과 가 아 닙 니 다.
\#예 를 들 어 아래 의 루틴,global 을 추가 하지 않 았 다 면flag 표지 전역 변 수 는 나타 납 니 다.논리 적 으로 마지막 결 과 는 20000 이지 만(이렇게 큰 숫자 를 선택 한 이 유 는\#이 문 제 를 더욱 뚜렷하게 볼 수 있 기 때 문 입 니 다).
\#하지만 사실은 이 결과 가 아니 라 20000 이하 의 결과 입 니 다.하지만 배출 하지 않 으 면 우연히 20000 이 나타 납 니 다.이것 은 매우 이상 적 인 결과 입 니 다.이것 은 왜 일 까요?
\#주로 스 레 드 가 cpu 에 호출 되 는 순서 가 확실 하지 않 습 니 다.구체 적 으로 말 하면 메 인 스 레 드 가 두 개의 키 스 레 드 를 만 들 때 각각 t1 과 t2 이 고 그들 은 각각 func 1()과 func 2()를 가리킨다.
\#이 두 스 레 드 의 함수 중 에 모두"global"이 있 습 니 다.num+=1"컴퓨터 내부 cpu 에서 실 행 될 때 이 문 구 는 실제 두 가지 과정 입 니 다.첫 번 째 과정 은 메모리 에서 global 을 읽 는 것 입 니 다.num 의 값,추가 작업 완료,이때 globalnum 의 값 은 원래 의 값 입 니 다.두 번 째 과정 은 구 화의 값 을 글로벌 에 지불 하 는 것 입 니 다num,이때 globalnum 값 이 업 데 이 트 됩 니 다.프로그램 실행 중 에 이런 게 나 와 요.
\#상황:cpu 가 스 레 드 t1 의 문 구 를 실행 하고 그 문 구 를 구 할 때 첫 번 째 과정 을 수행 한 후에 멈 추고 스 레 드 t1 을 던 지고 스 레 드 t2 를 실행 합 니 다.스 레 드 가 실 행 된 후에 도 이 상황 이 발생 합 니 다.
\#스 레 드 t1 을 실행 하 는 과정 이 있 습 니 다.이때 구 화 문 구 를 실행 하 는 두 번 째 과정 이 있 습 니 다.최초의 대 가 를 완성 하면 그 동안 의 전체 구 화 는 하지 않 은 것 과 같 습 니 다.그래서 이 마지막 결 과 는 20000 이 아 닙 니 다.\#상황 이 나타 납 니 다.
\#이런 상황 을 해결 하려 면 변 수 를 추가 하고'폴 링'방식 으로 실행 할 수 있 지만 이렇게 하 는 효율 이 낮 고 cpu 를 낭비 하기 때문에 보통'알림'방식 으로 합 니 다.
폴 링 방식:
from threading import Thread
global_num = 0
global_flag = 0
def func1():
global global_num
global global_flag
if global_flag == 0:
for i in range(1000000):
global_num += 1
global_flag = 1
print('---------func1:global_num=%s--------'%global_num)
def func2():
global global_num
while True:
if global_flag != 0:
for i in range(1000000):
global_num += 1
break
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
실행 결과:
global_num=0
---------func1:global_num=1000000--------
--------fun2:global_num=2000000
알림 모드:
from threading import Thread,Lock
global_num = 0
def func1():
global global_num
for i in range(1000000):
lock.acquire()# , , , , ,
global_num += 1
lock.release()
print('---------func1:global_num=%s--------'%global_num)
def func2():
global global_num
for i in range(1000000):
lock.acquire()
global_num += 1
lock.release()
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)
lock = Lock()
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
출력 결과:
global_num=0
---------func1:global_num=1901175--------
--------fun2:global_num=2000000
이상 의 python 진급 의 다 중 스 레 드 가 같은 전역 변 수 를 처리 하 는 방법 은 바로 작은 편집 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.여러분 께 참고 가 되 고 저 희 를 많이 사랑 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.