赞
踩
threading库是python的线程模型,利用threading库我们可以轻松实现多线程任务。
通过上图,我们可以直观的总结出进程、线程及其之间的关系与特点:
此外,多进程多线程也必须考虑硬件资源的架构:
python的多线程并非真正意义上的多线程,由于全局解释器锁(GIL)的存在,python中的线程只有在获得GIL后才拥有运行权限,而GIL同一时刻只能被一个线程所拥有。
python在运行计算密集型的多线程程序时,更倾向于让线程在整个时间片内始终占据GIL,而I/O密集型的多线程程序在I/O被调用前会释放GIL,允许其他线程在I/O执行时获得GIL,因此python的多线程更适用于I/O密集型的程序(网络爬虫)。
守护线程是指在程序运行时在后台提供一种通用服务的线程,比如垃圾回收线程;这种线程在程序中并非不可或缺。
默认创建的线程为非守护线程,等所有的非守护线程结束后,程序也就终止了,同时杀死进程中的所有守护线程。
只要非守护线程还在运行,程序就不会终止。
import threading import time #将创建的函数传递进threading.Thread()对象 def func(): print(threading.current_thread().getName()) t1 = threading.Thread(target=func,name='test_threading_1') t1.start() t1.join() #继承threading.Thread类,改写run()方法 class TestThread(threading.Thread): def __init__(self,name): super(TestThread,self).__init__() self.name = name def run(self): print(f'线程{self.name}正在进行!') n = 0 while n < 5: n += 1 print(f'线程{self.name}>>>{n}') time.sleep(1) print(f'线程{self.name}结束运行') t1 = TestThread('thread-1') t2 = TestThread('thread-2') t1.start() t2.start()
锁被用来实现对共享资源的同步访问;通过为每一个共享资源创建一个Lock对象,我们需要访问该资源时只能通过条用acquire方法来获取锁对象,待资源访问结束后,调用release方法释放Lock对象。
from threading import Thread,Lock import time lock = Lock() def func(): global n #加锁 lock.acquire() team = n time.sleep(1) n = team-1 #释放锁 lock.release() if __name__ == '__main__': n = 100 l = [] for i in range(100): t = Thread(target=func) l.append(t) t.start() for t in l: #将t线程设置成阻塞状态,直到t线程执行完后才能进入下一线程 t.join() print(n)
from threading import Thread,Lock x = 0 lock = Lock() def func(): global x lock.acquire() for i in range(6000): x = x+1 lock.release() if __name__ == '__main__': t1 = Thread(target=func) t2 = Thread(target=func) t3 = Thread(target=func) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() print(x)
在应用锁对象时,会发生死锁;死锁是指两个或两个以上的线程在执行过程中,因争夺资源访问权而造成的互相等待的现象,从而一直僵持下去。
递归锁对象就是用来解决死锁问题的,RLock对象内部维护着一个Lock和一个counter变量,counter记录着acquire的次数,从而使得资源可以被多次acquire,直到一个线程的所有acquire都被release时,其他线程才能够acquire资源。
from threading import Thread,RLock,currentThread import time rlock1 = rlock2 = RLock() class Test(Thread): def run(self): self.task1() self.task2() def task1(self): rlock1.acquire() print(f'{self.name}获得锁1') rlock2.acquire() print(f'{self.name}获得锁2') rlock2.release() print(f'{self.name}释放锁2') rlock1.release() print(f'{self.name}释放锁1') def task2(self): rlock2.acquire() print(f'{self.name}获得锁2') time.sleep(1) rlock1.acquire() print(f'{self.name}获得锁1') rlock1.release() print(f'{self.name}释放锁1') rlock2.release() print(f'{self.name}释放锁2') for i in range(3): t = Test() t.start()
import threading import time condition_lock = threading.Condition() PRE = 0 def pre(): print(PRE) return PRE def test_thread_hi(): condition_lock.acquire() print('wait for the commend of test_thread_hello') condition_lock.wait_for(pre) print('contain doing') condition_lock.release() def test_thread_hello(): time.sleep(1) condition_lock.acquire() global PRE PRE = 1 print('change PRE to 1') print('tell the test_thread_hi to acquire lock') condition_lock.notify() condition_lock.release() print('you need lock?') def main(): thread_hi = threading.Thread(target=test_thread_hi) thread_hello = threading.Thread(target=test_thread_hello) thread_hi.start() thread_hello.start() if __name__ == '__main__': main()
一个信号量管理一个内部计数器,acquire( )方法会减少计数器,release( )方法则增加计算器,计数器的值永远不会小于零,当调用acquire( )时,如果发现该计数器为零,则阻塞线程,直到调用release( ) 方法使计数器增加。
import threading import time semaphore4 = threading.Semaphore(4) def thread_semaphore(index): semaphore4.acquire() time.sleep(2) print('thread_%s is runing'%index) semaphore4.release() def main(): for index in range(9): threading.Thread(target=thread_semaphore,args=(index,)).start() if __name__ == '__main__': main()
如果一个或多个线程需要知道另一个线程的某个状态才能进入下一步的操作,就可以使用线程的event事件对象来处理。
import threading import time event = threading.Event() def student_exam(student_id): print('学生%s等监考老师发卷'%student_id) event.wait() print('开始考试了') def invigilate_teacher(): time.sleep(3) print('考试时间到了,学生们可以考试了') event.set() def main(): for student_id in range(5): threading.Thread(target=student_exam,args=(student_id,)).start() threading.Thread(target=invigilate_teacher).start() if __name__ == '__main__': main()
表示一个操作需要在等待一段时间之后执行,相当于一个定时器。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。