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 진급 의 다 중 스 레 드 가 같은 전역 변 수 를 처리 하 는 방법 은 바로 작은 편집 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.여러분 께 참고 가 되 고 저 희 를 많이 사랑 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기