쓰레드 모듈. import threading으로 임포트합니다. import thread가 있긴하지만
threading이 더 최신에 나온것이고 쓰기 쉽다고 어디 써있었는데 제가 둘다 써봤는데 threading모듈
내부에는 세마포어도 자동으로 있어서 더 쓰기가 쉬워요.
쓰레드 쓰기. 1. 쓰레드 인스턴스 생성해준다.
ex) th = threading.Thread()같은 형식으로 만들어줍니다. th에는 만들어진 쓰레드 인스턴스가,
첫번째 인자는 쓰레드로 돌릴 함수 target=돌릴함수이름,
두번째 인자는 쓰레드로 돌릴 함수의 인자인데 여기서 인자로 튜플을 받습니다. args=() 이런형식
으로 받아요. 코드.
import urllib2,threading def thread_even(i): print i def thread_odd(i): print i for i in range(0,10): if i%2==0: th = threading.Thread(target=thread_even,args=(i,)) th.start() if i%2==1: th2 = threading.Thread(target=thread_odd,args=(i,)) th2.start()
대충 해석이 되실겁니다. 0~10사이를 포문으로 돌리되 짝수면 thread_even이라는 쓰레드로 돌리고,
아니면 thread_odd라는 함수로 출력합니다. 여기서 인자를 줄 시에 한개면 반드시 끝에 ,를 붙여줘야
합니다. 이거 안 붙여주면 에러뜹니다. 이유를 몰라서 파이썬마을에 물어봤더니 이렇게해야
시퀀스의 하나인 튜플이 된다네요?
*추가.
args=(i)의 경우 args=i와 같습니다. 하지만 args=(i,)의 경우 튜플 형태로 인자가 넘어갑니다. 그러므로 이렇게 해줘야 합니다. 예시로 2버전에서 print시 print 1과 print (1) 나 print((1))은 같은 1을 출력하지만, (1,)은 (1,)그대로를 출력합니다. 파이썬에서 튜플로 인식했다는 거죠. 튜플로 인식하게끔 하기 위해 이렇게 합니다.
그리고 만들어진 인스턴스.start()메소드로 쓰레드를 시작합니다. 이게 실질적으로 시작하는
메소드에요. 쓰레드에서 따로 더 설명할건 없다고 봅니다. 첫번째 인자로 쓰레드로 돌릴 함수
두번째 인자로 넘길 인자를 튜플 형태로 한 후 start()메소드로 시작. 이게 기본입니다.
웹해킹시 쓰레드 모듈도 알아두는게 좋아요. 웹 레이스컨디션 문제도 있어서....
간단하게 세마포어에 관해서도 쓰겠습니다.
세마포어가 뭔지 모르시겠으면 이것저것 찾아보세요. 간단하게 설명하자면 두 쓰레드에서 한 변수에
접근해서 값을 바꿀시 한 쓰레드가 값을 바꾸기도 전에 다른 쓰레드가 와서 값을 바꿔버리면 값이
깨져버립니다. 그걸 방지하기 위해서 한 쓰레드만 값에 접근하도록 하는게 세마포어라고 아시면
됩니다.
예제코드.
import threading sum = 0 def thread_inc(): global sum for i in range(0,50000): sum = sum + 1 def thread_des(): global sum for i in range(0,50000): sum = sum - 1 thread_tuple=[] for i in range(0,100): if i%2==0: th = threading.Thread(target=thread_inc,args=()) thread_tuple.append(th) th.start() else: th2 = threading.Thread(target = thread_des, args=()) thread_tuple.append(th2) th2.start() for th in thread_tuple: th.join() print 'sum =',sum
100번 반복하면서 짝수일때 sum의 값을 50000 증가, 홀수일때는 50000 감소시킵니다. 글로벌변수를
쓰기 때문에 두 쓰레드에서 한 값에 접근하는 예입니다. 생각대로라면 0이 나와야겠죠? 50000증가,
50000감소를 똑같은 횟수대로 하니까요. 하지만 위에서 말했듯이 두 쓰레드가 한 값에 접근하면서
값이 깨져버려서 이상한 값이 출력됩니다.
매번 돌릴때마다 다르게 나올겁니다. 여기서 세마포어 만드는법과 간단한 설명을 하겠습니다.
세마포어 인스턴스는 이런식으로 만듭니다. sem = threading._Semaphore()
sem이라는 변수에 세마포어 인스턴스가 들어갑니다. 값을 들어갈때는 sem.acquire()로 들어가고,
나올때는 sem.release()로 나옵니다. 화장실에 들어갈때 잠그고 들어가서 끝날땐 열고 나오는거라
보시면 되요.
제대로 고쳐진 코드입니다.
import threading sum = 0 sem = threading._Semaphore() def thread_inc(): global sum sem.acquire() for i in range(0,50000): sum = sum + 1 sem.release() def thread_des(): global sum sem.acquire() for i in range(0,50000): sum = sum - 1 sem.release() thread_tuple=[] for i in range(0,100): if i%2==0: th = threading.Thread(target=thread_inc,args=()) thread_tuple.append(th) th.start() else: th2 = threading.Thread(target = thread_des, args=()) thread_tuple.append(th2) th2.start() for th in thread_tuple: th.join() print 'sum =',sum
'Python > 2.7 information' 카테고리의 다른 글
유효한 웹페이지 찾기? (0) | 2014.10.17 |
---|---|
소켓과 urllib2 속도차이 (2) | 2014.08.21 |
파이썬 소켓 기본. (2) | 2014.08.10 |
파이썬 리스트 관련 (0) | 2014.08.10 |
md5, sha1, base64등의 인코딩,디코딩 (2) | 2014.08.10 |