Python 다 중 스 레 드 닭 의 해 는 계 륵 이 아니다.
21059 단어 Python스 레 드[프로 그래 밍 언어]
처음에 python 다 중 스 레 드 를 배 웠 을 때 인터넷 검색 자 료 는 거의 거꾸로 반응 하 는 python 이 진정한 의미 의 다 중 스 레 드 가 없 었 고 python 다 중 스 레 드 는 바로 계 륵 이 었 다.그 때 는 알 수 없 었 기 때문에 python 이 GIL 해석 기 잠 금 을 가 진 다 는 개념 을 알 게 되 었 을 뿐 같은 시간 에 하나의 스 레 드 만 실행 되 고 IO 작업 을 만 나 야 전환 을 풀 수 있 습 니 다.그렇다면 python 다 중 스 레 드 는 정말 계 륵 이 아 닐 까?이 의혹 을 해결 하려 면, 나 는 반드시 직접 테스트 를 해 야 한다 고 생각한다.
python 과 자바 의 다 중 스 레 드 테스트 를 통 해 저 는 python 다 중 스 레 드 의 효율 이 자바 보다 못 하 다 는 것 을 알 게 되 었 습 니 다. 그러나 아직 닭 갈비 정도 에 이 르 지 못 했 습 니 다. 그러면 다른 메커니즘 과 비교 해 볼 까요?
관점: 다 중 스 레 드 수 요 를 다 중 프로 세 스 로 대체 합 니 다.
여러 편의 박문 을 전전 했다. 나 는 일부 네티즌 들 의 관점 을 보 았 다. 다 중 프로 세 스 가 GIL 의 제한 을 받 지 않 기 때문에 python 다 중 프로 세 스 를 사용 해 야 한다 고 생각 했다.그래서 저 는 여러 프로 세 스 를 사용 하여 병발 문 제 를 해결 하기 시 작 했 습 니 다. 그 동안 에 도 일부 구 덩이 를 만 났 습 니 다. 다행히 대부분 자 료 를 찾 아 해결 한 다음 에 여러 프로 세 스 를 간단하게 모 아서 Python 다 중 프로 세 스 를 소개 하 였 습 니 다.
그렇다면 다 중 프로 세 스 가 다 중 스 레 드 를 완전히 대체 할 수 있 습 니까?서 두 르 지 말고 우리 계속 내 려 다 보 자.
관점: 협 정 이 최선 의 방안 이다.
협 정의 개념 은 현재 비교적 뜨 거 운 것 이다. 협 정 이 스 레 드 와 다른 부분 은 협 정 이 운영 체제 에서 전환 하 는 것 이 아니 라 프로그래머 인 코딩 으로 전환 하 는 것 이다. 즉, 전환 은 프로그래머 가 제어 하 는 것 이기 때문에 스 레 드 라 는 안전 문제 가 없다.협의 과정의 개념 이 매우 넓 고 깊 기 때문에 본 고 는 구체 적 인 소 개 를 하지 않 고 나중에 단독으로 성문 화 될 것 이다.
테스트 데이터
자, 인터넷 의 관점 은 다 중 프로 세 스 나 협 정 을 사용 하여 다 중 스 레 드 (물론 프로 그래 밍 언어 를 바 꾸 고 해석 기 를 바 꾸 는 방법 은 제외) 를 대체 하 는 것 이 아 닙 니 다. 그러면 우 리 는 이 세 사람의 성능 차 이 를 테스트 해 보 겠 습 니 다.공정 한 테스트 를 하려 면 IO 집약 형 과 CPU 집약 형 문 제 를 고려 해 두 그룹 으로 나 눠 테스트 해 야 한다.
IO 밀집 형 테스트
IO 밀집 형 을 테스트 합 니 다. 저 는 가장 자주 사용 하 는 파충류 기능 을 선택 하여 파충류 가 bing 에 접근 하 는 데 필요 한 시간 을 계산 합 니 다.(주로 다 중 스 레 드 와 협 정 을 테스트 합 니 다. 단일 스 레 드 와 다 중 프로 세 스 는 예측 할 수 없습니다. 필요 하지 않 기 때 문 입 니 다)
테스트 코드:
#! -*- coding:utf-8 -*-
from gevent import monkey;monkey.patch_all()
import gevent
import time
import threading
import urllib2
def urllib2_(url):
try:
urllib2.urlopen(url,timeout=10).read()
except Exception,e:
print e
def gevent_(urls):
jobs=[gevent.spawn(urllib2_,url) for url in urls]
gevent.joinall(jobs,timeout=10)
for i in jobs:
i.join()
def thread_(urls):
a=[]
for url in urls:
t=threading.Thread(target=urllib2_,args=(url,))
a.append(t)
for i in a:
i.start()
for i in a:
i.join()
if __name__=="__main__":
urls=["https://www.bing.com/"]*10
t1=time.time()
gevent_(urls)
t2=time.time()
print 'gevent-time:%s' % str(t2-t1)
thread_(urls)
t4=time.time()
print 'thread-time:%s' % str(t4-t2)
테스트 결과:
방문 10 회
gevent-time:0.380326032639
thread-time:0.376606941223
방문 50 회
gevent-time:1.3358900547
thread-time:1.59564089775
100 회 방문
gevent-time:2.42984986305
thread-time:2.5669670105
방문 300 회
gevent-time:6.66330099106
thread-time:10.7605059147
결 과 를 통 해 알 수 있 듯 이 병발 수가 계속 증가 할 때 협 정의 효율 은 다 중 스 레 드 보다 높 지만 병발 수가 그렇게 높 지 않 을 때 이들 의 차이 가 크 지 않다.
CPU 밀집 형
CPU 밀집 형, 나 는 과학적 으로 계산 하 는 일부 기능 을 선택 하여 필요 한 시간 을 계산한다.(주요 테스트 단일 스 레 드, 다 중 스 레 드, 협 정, 다 중 프로 세 스)
테스트 코드:
#! -*- coding:utf-8 -*-
from multiprocessing import Process as pro
from multiprocessing.dummy import Process as thr
from gevent import monkey;monkey.patch_all()
import gevent
def run(i):
lists=range(i)
list(set(lists))
if __name__=="__main__":
'''
'''
for i in range(30): ##10-2.1s 20-3.8s 30-5.9s
t=pro(target=run,args=(5000000,))
t.start()
'''
'''
# for i in range(30): ##10-3.8s 20-7.6s 30-11.4s
# t=thr(target=run,args=(5000000,))
# t.start()
'''
'''
# jobs=[gevent.spawn(run,5000000) for i in range(30)] ##10-4.0s 20-7.7s 30-11.5s
# gevent.joinall(jobs)
# for i in jobs:
# i.join()
'''
'''
# for i in range(30): ##10-3.5s 20-7.6s 30-11.3s
# run(5000000)
테스트 결과:
동시 다발 10 회: [다 중 프로 세 스] 2.1s [다 중 스 레 드] 3.8s 【 협 정 】 4.0s [싱글 스 레 드] 3.5s 동시 다발 20 회: [다 중 프로 세 스] 3.8s [다 중 스 레 드] 7.6s [협 정] 7.7 s [싱글 스 레 드] 7.6s 동시 다발 30 회: [다 중 프로 세 스] 5.9s [다 중 스 레 드] 11.4s [협 정] 11.5s [단일 스 레 드] 11.3s 이 를 통 해 알 수 있 듯 이 CPU 밀집 형 테스트 에서 다 중 프로 세 스 효 과 는 다른 것 보다 현저히 좋 고 다 중 스 레 드, 협 정 과 단일 스 레 드 효과 가 많 지 않다.다 중 프로 세 스 만 CPU 의 컴 퓨 팅 능력 을 완전히 사 용 했 기 때문이다.코드 가 실 행 될 때, 다 중 프로 세 스 만 CPU 사용률 을 가득 채 울 수 있 음 을 볼 수 있 습 니 다.
본문 결론
두 조 의 데 이 터 를 통 해 우 리 는 python 다 중 스 레 드 가 그렇게 닭 갈비 가 아니 라 는 것 을 알 수 있다.만약 그렇지 않다 면, Python 3 는 왜 GIL 을 제거 하지 않 습 니까?이 문제 에 대해 Python 커 뮤 니 티 에 도 두 가지 의견 이 있 습 니 다. 여기 서 더 이상 논술 하지 않 고 Python 아버지의 결정 을 존중 해 야 합 니 다.
언제 다 중 스 레 드 를 사용 해 야 하 는 지, 언제 다 중 프로 세 스 를 사용 해 야 하 는 지, 언제 협 정 을 사용 해 야 하 는 지?답 이 분명 해 졌 을 거 야.
파충류 등 IO 밀집 형 프로그램 을 작성 해 야 할 때 다 중 스 레 드 나 협 정 (친 측 차이 가 뚜렷 하지 않 음) 을 사용 해 야 합 니 다.과학적 인 계산 이 필요 할 때 CPU 밀집 형 프로그램 을 설계 하려 면 다 중 프로 세 스 를 선택해 야 합 니 다.물론 이 같은 결론 의 전 제 는 분포 식 을 하지 않 고 한 서버 에서 만 테스트 하 는 것 이다.
답 은 이미 제시 되 었 는데, 본문 은 여기에서 끝 낼 것 인가?파 이 썬 다 중 스 레 드 가 아직 쓸모 가 있다 고 논 술 했 으 니 그 용법 을 소개 하 자.
Multiprocessing. dummy 모듈
Multiprocessing. dummy 용법 은 다 중 프로 세 스 Multiprocessing 용법 과 유사 합 니 다. 다만 import 패키지 에. dummy 를 추가 합 니 다.
용법 참조 Multiprocessing 용법
스 레 딩 모듈
이것 은 python 이 자체 적 으로 가지 고 있 는 threading 다 중 스 레 드 모듈 로 다 중 스 레 드 를 만 드 는 데 주로 두 가지 방식 이 있 습 니 다.하 나 는 threading 류 를 계승 하기 위해 다른 하 나 는 threading. Thread 함 수 를 사용 합 니 다. 다음은 이 두 가지 용법 을 소개 합 니 다.
Usage【1】
threading. Thread () 함수 로 스 레 드 를 만 듭 니 다.
코드:
def run(i):
print i
for i in range(10):
t=threading.Thread(target=run,args=(i,))
t.start()
설명: Thread () 함 수 는 2 개의 인자 가 있 습 니 다. 하 나 는 target 이 고 하위 스 레 드 가 실행 할 함수 이름 입 니 다.다른 하 나 는 args 로 전달 해 야 할 매개 변수 입 니 다.하위 스 레 드 를 만 들 면 대상 을 되 돌려 주 고 대상 의 start 방법 을 호출 하여 하위 스 레 드 를 시작 할 수 있 습 니 다.
스 레 드 대상 방법:
Start () 시작 스 레 드 의 실행 Run () 스 레 드 의 기능 을 정의 하 는 함수 스 레 드 가 끝 날 때 까지 Join (timeout = None) 프로그램 이 끊 깁 니 다.timeout 을 주면, 최대 timeout 초 를 차단 합 니 다.
getName () 스 레 드 이름 되 돌려 주기 setName () 스 레 드 이름 설정 isAlive () 불 표지, 이 스 레 드 가 실행 중인 지 여부 isDaemon () 스 레 드 로 돌아 가 는 daemon 로고 setDaemon (daemonic) 은 스 레 드 의 daemon 로 고 를 daemonic (start () 함수 전에 호출 해 야 합 니 다) 로 설정 합 니 다.
t. setDaemon (True) 은 부모 스 레 드 를 데 몬 스 레 드 로 설정 하고 부모 프로 세 스 가 끝 날 때 하위 프로 세 스 도 끝 납 니 다.
threading 클래스 의 방법:
threading. enumerate () 실행 중인 스 레 드 수 Usage【2】
threading 클래스 를 계승 하여 스 레 드 를 만 듭 니 다.
코드:
import threading
class test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
try:
print "code one"
except:
pass
for i in range(10):
cur=test()
cur.start()
for i in range(10):
cur.join()
설명: 이 방법 은 threading 류 를 계승 하고 run 함수 기능 을 재 구성 했다.
질문
때때로 우 리 는 모든 하위 스 레 드 의 반환 값 을 가 져 와 야 한다.그러나 일반 함 수 를 호출 하여 return 값 을 가 져 오 는 방식 은 다 중 스 레 드 에 적용 되 지 않 습 니 다.따라서 하위 스 레 드 반환 값 을 가 져 오 는 새로운 방법 이 필요 합 니 다.
코드:
import threading
class test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.tag=1
def get_result(self):
if self.tag==1:
return True
else:
return False
f=test()
f.start()
while f.isAlive():
continue
print f.get_result()
설명: 다 중 스 레 드 가 반환 값 을 얻 는 가장 중요 한 문 제 는 하위 스 레 드 가 언제 끝 납 니까?우 리 는 언제 반환 값 을 가 져 와 야 합 니까?isAlive () 방법 으로 하위 스 레 드 의 생존 여 부 를 판단 할 수 있 습 니 다.
제어 루틴 운행 수
수행 해 야 할 임무 가 매우 많 을 때, 우 리 는 종종 라인 의 수량 을 제어 해 야 한다. threading 류 는 라인 의 수량 을 제어 하 는 방법 을 가지 고 있다.
코드:
import threading
maxs=10 ##
threadLimiter=threading.BoundedSemaphore(maxs)
class test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
threadLimiter.acquire() #
try:
print "code one"
except:
pass
finally:
threadLimiter.release() #
for i in range(100):
cur=test()
cur.start()
for i in range(100):
cur.join()
설명: 상기 프로그램 은 다 중 스 레 드 병발 수 를 10 으로 제어 할 수 있 으 며 이 수량 을 초과 하면 이상 을 일 으 킬 수 있 습 니 다.
자체 적 인 방법 을 제외 하고 우 리 는 다른 방안 도 설계 할 수 있다.
threads=[]
'''
'''
for i in range(10):
t=threading.Thread(target=run,args=(i,))
threads.append(t)
'''
'''
for t in threads:
t.start()
while True:
# , 5 while ,
# for . while
if(len(threading.enumerate())<5):
break
이상 의 두 가지 방식 은 모두 가능 하 며, 본인 은 아래 의 그런 방식 을 사용 하 는 것 을 더욱 좋아 합 니 다.
다 중 프로 세 스 문 제 는 Python 다 중 프로 세 스 현장 으로 갈 수 있 습 니 다. 다 중 스 레 드 문제 에 대해 서 는 아래 에 댓 글 을 달 아 토론 할 수 있 습 니 다.
설명: 본 고 는 오리지널 이 라 고 할 수 없습니다. 그 중에서 인터넷 에서 많은 소 들 의 글 을 참고 하 였 습 니 다. 저 는 이 테스트 에서 Python 다 중 스 레 드 와 관련 된 문 제 를 논술 하고 Python 다 중 스 레 드 의 기본 적 인 용법 을 간단하게 소개 하여 초보 친구 들 에 게 의혹 을 풀 어 주 었 습 니 다.
기술 에는 전공 이 있 는데, 이와 같 을 뿐이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.