python---线程与进程
一 线程
1.1 概述
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
Threading用于提供线程相关的操作:
import threading import time def show(arg): time.sleep(1) print ('thread'+str(arg)) for i in range(10): t = threading.Thread(target=show, args=(i,)) t.start() print ('main thread stop') >>>main thread stop >>>thread0 >>>thread6 >>>thread3 >>>thread2 >>>thread5 >>>thread4 >>>thread1 >>>thread7 >>>thread8 >>>thread9
上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。
注:后台线程行为: 只要你的主线程执行完毕了,后台线程,不管你执行到哪里了,就直接关闭了。前台线程行为: 主程序执行过程中,前台线程也在执行,主程序执行完毕后,等待前台线程也执行完成后,程序结束。
start #线程准备就绪,等待CPU调度 setName #为线程设置名称 getName #获取线程名称 setDaemon #设置为后台线程或前台线程(默认),如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止 如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止 join #逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义 run #线程被cpu调度后自动执行线程对象的run方法
1.2 线程锁(Lock,RLock)
由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 同一时刻允许一个线程执行操作。
import threading import time gl_num = 0 def show(arg): global gl_num time.sleep(1) gl_num +=1 print (gl_num,end=' ') for i in range(10): t = threading.Thread(target=show, args=(i,)) t.start() print ('main thread stop') >>>main thread stop >>>1 2 3 4 5 6 7 8 9 10
import threading import time gl_num = 0 lock = threading.RLock() def Func(): lock.acquire() global gl_num gl_num +=1 time.sleep(1) print (gl_num) lock.release() for i in range(10): t = threading.Thread(target=Func) t.start()
1.3 信号量(semaphore)
多线程编程的最常见问题是数据共享。当多个线程都修改某一个共享数据的时候,需要进行同步控制。线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
而互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
import threading,time def run(n): semaphore.acquire() time.sleep(2) print("run the thread: %s" %n) semaphore.release() if __name__ == '__main__': num= 0 semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行 for i in range(20): t = threading.Thread(target=run,args=(i,)) t.start()
1.4 事件(event)
python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。事件处理的机制:全局定义了一个“Flag”,clear将“Flag”设置为False,set将“Flag”设置为True。如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。
import threading def do(event): print ('start') event.wait() print ('execute') event_obj = threading.Event() for i in range(10): t = threading.Thread(target=do, args=(event_obj,)) t.start() event_obj.clear() inp = input('input:') if inp == 'true': event_obj.set()
1.5 timer
定时器,指定n秒后执行某操作
from threading import Timer def hello(): print("hello, world") t = Timer(1, hello) t.start() # after 1 seconds, "hello, world" will be printed
二 进程
2.1 进程的创建
from multiprocessing import Process import time def worker(interval): n = 5 while n > 0: print("The time is {0}".format(time.ctime())) time.sleep(interval) n -= 1 if __name__ == "__main__": p = Process(target = worker, args = (3,)) p.start() print ("p.pid:", p.pid) print ("p.name:", p.name) print ("p.is_alive:", p.is_alive()) >>>p.pid: 5360 >>>p.name: Process-1 >>>p.is_alive: True >>>The time is Thu Jul 12 18:57:23 2018 >>>The time is Thu Jul 12 18:57:26 2018 >>>The time is Thu Jul 12 18:57:29 2018 >>>The time is Thu Jul 12 18:57:32 2018 >>>The time is Thu Jul 12 18:57:35 2018
import multiprocessing import time def worker_1(interval): print ("worker_1") time.sleep(interval) print ("end worker_1") def worker_2(interval): print ("worker_2") time.sleep(interval) print ("end worker_2") def worker_3(interval): print ("worker_3") time.sleep(interval) print ("end worker_3") if __name__ == "__main__": p1 = multiprocessing.Process(target = worker_1, args = (2,)) p2 = multiprocessing.Process(target = worker_2, args = (3,)) p3 = multiprocessing.Process(target = worker_3, args = (4,)) p1.start() p2.start() p3.start() print("The number of CPU is:" + str(multiprocessing.cpu_count())) for p in multiprocessing.active_children(): print("child p.name:" + p.name + "\tp.id" + str(p.pid)) print ("END!!!!!!!!!!!!!!!!!") >>>The number of CPU is:4 >>>child p.name:Process-1 p.id5196 >>>child p.name:Process-2 p.id8680 >>>child p.name:Process-3 p.id2732 >>>END!!!!!!!!!!!!!!!!! >>>worker_2 >>>worker_1 >>>worker_3 >>>end worker_1 >>>end worker_2 >>>end worker_3
注意:(1)由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。
(2)进程各自持有一份数据,默认无法共享数据
2.2 daemon
子进程设置了daemon属性时,主进程结束,它们就随着结束了。(线程也有deamon操作)
import multiprocessing import time def worker(interval): print("work start:{0}".format(time.ctime())); time.sleep(interval) print("work end:{0}".format(time.ctime())); if __name__ == "__main__": p = multiprocessing.Process(target = worker, args = (3,)) p.start() print ("end!") >>>end! >>>work start:Thu Jul 12 19:12:51 2018 >>>work end:Thu Jul 12 19:12:54 2018
import multiprocessing import time def worker(interval): print("work start:{0}".format(time.ctime())); time.sleep(interval) print("work end:{0}".format(time.ctime())); if __name__ == "__main__": p = multiprocessing.Process(target = worker, args = (3,)) p.daemon = True p.start() print ("end!") >>>end!
参考:https://www.cnblogs.com/yuanchenqi/articles/5733873.html
https://www.cnblogs.com/wupeiqi/articles/5040827.html