一 线程
1.1 概述
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
Threading用于提供线程相关的操作:
import threading import timedef 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 timegl_num = 0def show(arg):global gl_numtime.sleep(1)gl_num +=1print (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 timegl_num = 0lock = threading.RLock()def Func():lock.acquire()global gl_numgl_num +=1time.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,timedef run(n):semaphore.acquire()time.sleep(2)print("run the thread: %s" %n)semaphore.release()if __name__ == '__main__':num= 0semaphore = 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 threadingdef 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 Timerdef 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 timedef worker(interval):n = 5while n > 0:print("The time is {0}".format(time.ctime()))time.sleep(interval)n -= 1if __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 timedef 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 timedef 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 timedef 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 = Truep.start()print ("end!")>>>end!
参考:https://www.cnblogs.com/yuanchenqi/articles/5733873.html
https://www.cnblogs.com/wupeiqi/articles/5040827.html