>  기사  >  백엔드 개발  >  파이썬 스레드 관행

파이썬 스레드 관행

巴扎黑
巴扎黑원래의
2016-12-09 10:42:441245검색

"""" Python에서 스레드를 사용하는 방법에는 두 가지가 있습니다. 스레드 개체를 래핑하는 함수 또는 클래스입니다.

1. 기능: 스레드 모듈에서 start_new_thread() 함수를 호출하여 새 스레드를 생성합니다. 스레드가 자연스럽게 끝날 때까지 기다리거나 스레드 함수에서 thread.exit() 또는 thread.exit_thread() 메서드를 호출하여 스레드를 종료할 수 있습니다.
가져오기 시간
가져오기 스레드

def 타이머(no,interval):
cnt=0

while cnt<10:
print 'thread(%d) )'%(cnt)
time.sleep(간격)
cnt=cnt+1


def test():
thread.start_new_thread(timer,(1,1) ))
thread.start_new_thread(timer,(2,2))

if __name__=='__main__':
'스레드 시작' 인쇄
test()
시간. sleep(20)
thread.exit_thread()
print 'exit...'
2. threading.Thread의 하위 클래스를 생성하여 스레드 객체를 래핑합니다.
threading.Thread 클래스 사용법:

1, 자신의 스레드 클래스의 __init__에서 threading.Thread.__init__(self, name = threadname)을 호출합니다.

Threadname은 스레드의 이름입니다.

2, run()은 일반적으로 필요한 기능을 구현하기 위해 다시 작성되고 작성되어야 합니다.

3. getName(), 스레드 개체 이름 가져오기

4. setName(), 스레드 개체 이름 설정

5. 🎜>
6, jion([timeout]), 실행하기 전에 다른 스레드가 끝날 때까지 기다립니다.

7, setDaemon(bool)은 하위 스레드가 메인 스레드로 끝나는지 여부를 설정하며 start() 이전에 호출되어야 합니다. 기본값은 거짓입니다.

8, isDaemon()은 스레드가 메인 스레드로 끝나는지 여부를 결정합니다.

9, isAlive(), 스레드가 실행 중인지 확인합니다.
가져오기 스레딩
가져오기 시간

클래스 타이머(threading.Thread):
def __init__(self,num,interval):
threading.Thread.__init__(self)
self.thread_num=num
self.interval=interval
self.thread_stop=False

def run(self):
while not self.thread_stop:
print 'thread 객체 (%d), 시간 %sn' %(self.thread_num,time.ctime())
time.sleep(self.interval)

def stop(self):
self.thread_stop =True

def test():
thread1=timer(1,1)
thread2=timer(2,2)
thread1.start()
thread2.start( )
time.sleep(10)
thread1.stop()
thread2.stop()
return

if __name__=='__main__':
test()
"""
"""
문제의 원인은 동일한 리소스에 대한 여러 스레드의 액세스가 제어되지 않아 데이터가 손상되고 스레드 작업의 결과를 예측할 수 없게 되기 때문입니다. 이 현상을 "스레드 안전하지 않음"이라고 합니다.
import threading
import time

class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep (1)
msg='나는 '+ self.getName()+'@'+str(i)
print msg

def test():
for i in range (5):
t=MyThread()
t.start()

if __name__=='__main__':
test()

위의 예는 다음과 같습니다. 멀티스레드 프로그래밍의 가장 일반적인 문제는 데이터 공유입니다. 여러 스레드가 특정 공유 데이터를 수정하는 경우 동기화 제어가 필요합니다.

스레드 동기화는 여러 스레드가 경쟁 리소스에 안전하게 액세스하도록 보장할 수 있습니다. 가장 간단한 동기화 메커니즘은 뮤텍스 잠금을 도입하는 것입니다. 뮤텍스는 리소스에 잠금/잠금 해제 상태를 도입합니다. 스레드가 공유 데이터를 변경하려면 먼저 이를 잠가야 합니다. 이때 리소스 상태는 "잠김"이며 스레드가 리소스를 해제하고 리소스 상태를 "로 변경할 때까지 다른 스레드는 이를 변경할 수 없습니다. 잠금 해제됨"이면 다른 스레드가 리소스를 다시 잠글 수 있습니다. 뮤텍스 잠금은 한 번에 하나의 스레드만 쓰기 작업을 수행하도록 하여 다중 스레드 상황에서 데이터의 정확성을 보장합니다. 그 중 잠금 메소드 획득은 타임아웃 기간 동안 선택적 매개변수 타임아웃을 가질 수 있습니다. 시간 초과가 설정된 경우 반환 값을 사용하여 시간 초과 후 잠금이 획득되었는지 여부를 확인하여 다른 처리를 수행할 수 있습니다.

Lock 클래스는 스레딩 모듈에서 정의됩니다
import threading
가져오기 시간

class MyThread(threading.Thread):
def run(self):
전역 숫자
time.sleep(1)

if mutex.acquire():
num=num+1
print self.name+' set num to '+str(num)+ 'n'
mutex.release()
num=0
mutex=threading.Lock()

def test():
for i in range(5):
t=MyThread()
t.start()

if __name__=='__main__':
test()
"""
"""간단 교착 상태 상황은 스레드가 동일한 리소스를 요청하기 위해 "반복"하여 교착 상태가 직접적으로 발생하는 경우입니다.
import threading
import time

class MyThread(threading.Thread):
def run (self):
전역 숫자
time.sleep(1)

if mutex.acquire(1):
num = num+1
msg = self .name+' set num을 '+str(num)으로
print msg
mutex.acquire()
mutex.release()
mutex.release()
num = 0
mutex = threading. Lock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
동일한 스레드에서 동일한 리소스에 대한 여러 요청을 지원하기 위해 Python은 "재진입 잠금"인 threading.RLock을 제공합니다. RLock은 내부적으로 Lock과 카운터 변수를 유지하며, 카운터는 획득 횟수를 기록하므로 리소스가 여러 번 필요할 수 있습니다. 스레드의 모든 획득이 해제될 때까지 다른 스레드가 리소스를 얻을 수 있습니다. 위의 예에서 Lock 대신 RLock을 사용하면 교착 상태가 발생하지 않습니다.
import threading
import time

class MyThread(threading.Thread):
def run(self) :
전역 숫자
time.sleep(1)

if mutex.acquire(1):
num = num+1
set msg = self.name+' num to ' +str (num)
print msg
num mutex.acquire()
mutex.release() mutex.release()
num = 0
mutex = threading. >def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
"""

"""
Python 멀티 스레드 프로그래밍(5): 조건 변수 동기화

Mutex 잠금은 가장 간단한 스레드 동기화 메커니즘이며 Python 개체에서 제공하는 조건입니다. 복잡한 스레드 동기화 문제에 대한 지원을 제공합니다. 조건은 잠금과 유사한 획득 및 해제 방법 외에도 대기 및 알림 방법도 제공합니다. 스레드는 먼저 조건 변수를 획득한 다음 일부 조건을 결정합니다. 조건이 충족되지 않으면 대기하고, 조건이 충족되면 일부 처리를 수행하여 조건을 변경하고, 대기 상태에 있는 다른 스레드는 알림을 받은 후 조건을 다시 판단합니다. 이 프로세스는 복잡한 동기화 문제를 해결하기 위해 지속적으로 반복됩니다.

Condition 객체는 잠금(Lock/RLock)과 대기 풀을 유지한다고 생각하면 됩니다. 스레드는 acquire를 통해 Condition 객체를 획득하며, 스레드는 Condition 내부의 잠금을 해제하고 동시에 대기 풀에 기록됩니다. 알림 메서드가 호출되면 Condition 개체는 대기 풀에서 스레드를 선택하고 잠금 획득을 시도하기 위해 획득 메서드를 호출하도록 알립니다.

Condition 개체의 생성자는 Lock/RLock 개체를 매개 변수로 허용할 수 있습니다. 지정하지 않으면 Condition 개체가 내부적으로 RLock을 생성합니다.

Notify 메소드 외에도 Condition 객체는 대기 풀의 모든 스레드에 내부 잠금 획득을 시도하도록 알릴 수 있는 informAll 메소드도 제공합니다. 위 메커니즘으로 인해 대기 상태에 있는 스레드는 알림 메서드를 통해서만 깨울 수 있으므로, informAll의 기능은 스레드가 영원히 침묵하는 것을 방지하는 것입니다.

조건변수 동기화를 보여주는 고전적인 문제는 생산자와 소비자 문제입니다. 생산자 그룹(Producer)과 소비자 그룹(Consumer)이 시장을 통해 제품과 상호 작용한다고 가정합니다. 생산자의 "전략"은 시장에 남은 제품이 1,000개 미만이면 100개의 제품을 생산하여 시장에 출시하는 것이고, 소비자의 "전략"은 시장에 남은 제품이 100개보다 많으면 100개의 제품을 생산하는 것입니다. .3개 제품을 섭취하세요. 생산자와 소비자의 문제를 해결하기 위해 Condition을 사용하는 코드는 다음과 같습니다.
import threading
import time

class Producer(threading.Thread):
def run(self):
전역 개수
while True:
if con.acquire():
if count>1000:
con.wait()
else:
count=count+100
print self.name+' producer 100,count='+str(count)

con.release()
time.sleep(1)

class Customer(threading. 스레드):
def run(self):
전역 개수
while True:
if con.acquire():
if count>100:
count=count-100
print self .name+ 'consume 100, count='+str(count)
else:
con.wait()
con.release()
time.sleep(1)

count=500
con=threading.Condition()

def test():
for i in range(5):
p=Producer()
p.start( )
c=Customer()
c.start()
print i


if __name__=='__main__':
test()
python 기본적으로 전역 변수는 함수에서 읽을 수 있지만 쓸 수는 없습니다. 그러나
은 con에서만 읽을 수 있으므로 전역 """

을 도입할 필요가 없습니다.
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.