|
发表于 2020-2-25 02:46:19
|
显示全部楼层
本楼为最佳答案
线程
进程
每个进程都有自己的数据段,代码段,和堆栈段。
在子线程中对全局变量进行修改,对父进程中的全局变量没有影响
在创建子进程时对全局变量做了一个备份,父与子进程中的num是2个完全不同的变量
- from multiprocessing import Process
- import os
- num = 100
- def run(str):
- print("启动子线程")
- global num
- num += 1
- print("结束子线程")
- if __name__ == '__main__':
- print("主(父)进程启动----%s"%(os.getpid()))
- p = Process(target=run,args=("nice",))
- p.start()
- #让父进程等待子进程结束,再执行父进程
- p.join()
- print("父进程结束---%d"%(num))
复制代码
进程间的“通讯”,利用到队列,数据原则是先进先出,后进后出。你用一个进程去产生某些数据,并存早列队里面,另外一个进程往这个列队取数据,实现进程之间的“通讯”
- from multiprocessing import Process,Queue
- import os,time
- def write(Q):
- print("启动抓取子进程%s"%(os.getpid()))
- for chr in ["A","B","C","D"]:
- Q.put(chr) #往队列传数据
- time.sleep(1)
- print("结束抓取子进程程%s" % (os.getpid()))
- def read(Q):
- print("启动下载子进程%s"%(os.getpid()))
- while True:
- value = Q.get(True) #没有数据,阻塞
- print("value = ",value)
- print("结束下载子进程%s" % (os.getpid()))
- if __name__ == '__main__':
- #利用队列:由父进程创建队列,并传递给子进程,实现进程间的通讯
- print("父进程启动")
- q = Queue()
- writ = Process(target=write,args=(q,))
- rea = Process(target=read,args=(q,))
- writ.start()
- rea.start()
- writ.join()
- #rea进程里是个死循环,无法等待其结束 ,只能强行结束
- rea.terminate()
- print("父进程结束")
复制代码
多线程和多进程最大的不同在于,多进程中,同一个变量各自有一分拷贝存在每个进程中,互不影响
而多线程中,所有的变量都有所有线程共享。所以任何一个变量都可以被任意一个线程修改,
因此线程之间,共享数据最大的危险在于多个线程同时修改改一个变量,容易吧内容改乱。
如下代码当range大到一定数值,线程同时对数据修改,会产生不可估计的值。结果肯定不会为零
- from threading import Thread
- num = 0
- def run(n):
- global num
- for i in range(10):
- num += n #当线程同时执行到这里,num已经等于9,另外一个线程执行了 9 + 6 此时num=15
- num -= n #这里执行就变成 15 - 6
- if __name__ == '__main__':
- t1 = Thread(target=run,args=(6,))
- t2 = Thread(target=run,args=(9,))
- t1.start()
- t2.start()
- t1.join()
- t2.join()
- print("NUM =",num)
复制代码
线程锁解决数据混乱
- from threading import Thread,Lock
- #锁对象
- lock = Lock()
- num = 0
- def run(n):
- global num
- for i in range(10000000):
- '''
- # 加上线程锁
- #确保线程锁中,只能有一个线程存在执行
- #阻塞了多线程的并发执行,包含锁的某段代码实际上只能以单线程模式执行,所以效率消耗非常大
- #由于存在多个锁,不同线程持有不同的锁,并试图获取其他的锁,可能造成死锁,导致多个线程挂起(被挡在锁外面,一直等待),只能靠系统强制终止
- lock.acquire()
- try:
- num += n
- num -= n
- finally:
- #释放线程锁
- lock.release()
- '''
- #与上面代码功能相同,with lock ,可以自动上锁,与解锁
- with lock:
- num += n
- num -= n
- if __name__ == '__main__':
- t1 = Thread(target=run,args=(6,))
- t2 = Thread(target=run,args=(9,))
- t1.start()
- t2.start()
- t1.join()
- t2.join()
- print("NUM =",num)
复制代码 |
|