鱼C论坛

 找回密码
 立即注册
查看: 761|回复: 1

[已解决]线程和进程的问题!谢谢!

[复制链接]
发表于 2020-2-25 01:01:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这几天看了点关于进程和线程的只是,但是一直弄不明白python进程数据共享和线程数据共享的区别

哪位能指点一下!!!!  谢谢!!!!!!!!!!!!!
最佳答案
2020-2-25 02:46:19
线程
进程

每个进程都有自己的数据段,代码段,和堆栈段。
在子线程中对全局变量进行修改,对父进程中的全局变量没有影响
在创建子进程时对全局变量做了一个备份,父与子进程中的num是2个完全不同的变量
  1. from multiprocessing import Process
  2. import os
  3. num = 100
  4. def run(str):
  5.     print("启动子线程")
  6.     global num
  7.     num += 1
  8.     print("结束子线程")

  9. if __name__ == '__main__':
  10.     print("主(父)进程启动----%s"%(os.getpid()))
  11.     p = Process(target=run,args=("nice",))
  12.     p.start()
  13.     #让父进程等待子进程结束,再执行父进程
  14.     p.join()
  15.     print("父进程结束---%d"%(num))
复制代码


进程间的“通讯”,利用到队列,数据原则是先进先出,后进后出。你用一个进程去产生某些数据,并存早列队里面,另外一个进程往这个列队取数据,实现进程之间的“通讯”
  1. from multiprocessing import Process,Queue
  2. import os,time
  3. def write(Q):
  4.     print("启动抓取子进程%s"%(os.getpid()))
  5.     for chr in ["A","B","C","D"]:
  6.         Q.put(chr)  #往队列传数据
  7.         time.sleep(1)
  8.     print("结束抓取子进程程%s" % (os.getpid()))

  9. def read(Q):
  10.     print("启动下载子进程%s"%(os.getpid()))
  11.     while True:
  12.         value = Q.get(True)  #没有数据,阻塞
  13.         print("value = ",value)
  14.     print("结束下载子进程%s" % (os.getpid()))

  15. if __name__ == '__main__':
  16.     #利用队列:由父进程创建队列,并传递给子进程,实现进程间的通讯
  17.     print("父进程启动")
  18.     q = Queue()
  19.     writ = Process(target=write,args=(q,))
  20.     rea = Process(target=read,args=(q,))
  21.     writ.start()
  22.     rea.start()
  23.     writ.join()
  24.     #rea进程里是个死循环,无法等待其结束 ,只能强行结束
  25.     rea.terminate()
  26.     print("父进程结束")
复制代码


多线程和多进程最大的不同在于,多进程中,同一个变量各自有一分拷贝存在每个进程中,互不影响
而多线程中,所有的变量都有所有线程共享。所以任何一个变量都可以被任意一个线程修改,
因此线程之间,共享数据最大的危险在于多个线程同时修改改一个变量,容易吧内容改乱。
如下代码当range大到一定数值,线程同时对数据修改,会产生不可估计的值。结果肯定不会为零
  1. from threading import Thread
  2. num = 0

  3. def run(n):
  4.     global num
  5.     for i in range(10):
  6.         num += n  #当线程同时执行到这里,num已经等于9,另外一个线程执行了 9 + 6 此时num=15
  7.         num -= n #这里执行就变成  15 - 6

  8. if __name__ == '__main__':
  9.     t1 = Thread(target=run,args=(6,))
  10.     t2 = Thread(target=run,args=(9,))
  11.     t1.start()
  12.     t2.start()
  13.     t1.join()
  14.     t2.join()

  15.     print("NUM =",num)
复制代码


线程锁解决数据混乱
  1. from threading import Thread,Lock
  2. #锁对象
  3. lock = Lock()

  4. num = 0
  5. def run(n):
  6.     global num
  7.     for i in range(10000000):
  8.         '''
  9.         # 加上线程锁
  10.         #确保线程锁中,只能有一个线程存在执行
  11.         #阻塞了多线程的并发执行,包含锁的某段代码实际上只能以单线程模式执行,所以效率消耗非常大
  12.         #由于存在多个锁,不同线程持有不同的锁,并试图获取其他的锁,可能造成死锁,导致多个线程挂起(被挡在锁外面,一直等待),只能靠系统强制终止
  13.         lock.acquire()
  14.         try:
  15.             num += n
  16.             num -= n
  17.         finally:
  18.         #释放线程锁
  19.             lock.release()
  20.         '''
  21.         #与上面代码功能相同,with lock ,可以自动上锁,与解锁
  22.         with lock:
  23.             num += n
  24.             num -= n

  25. if __name__ == '__main__':
  26.     t1 = Thread(target=run,args=(6,))
  27.     t2 = Thread(target=run,args=(9,))
  28.     t1.start()
  29.     t2.start()
  30.     t1.join()
  31.     t2.join()
  32.     print("NUM =",num)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-2-25 02:46:19 | 显示全部楼层    本楼为最佳答案   
线程
进程

每个进程都有自己的数据段,代码段,和堆栈段。
在子线程中对全局变量进行修改,对父进程中的全局变量没有影响
在创建子进程时对全局变量做了一个备份,父与子进程中的num是2个完全不同的变量
  1. from multiprocessing import Process
  2. import os
  3. num = 100
  4. def run(str):
  5.     print("启动子线程")
  6.     global num
  7.     num += 1
  8.     print("结束子线程")

  9. if __name__ == '__main__':
  10.     print("主(父)进程启动----%s"%(os.getpid()))
  11.     p = Process(target=run,args=("nice",))
  12.     p.start()
  13.     #让父进程等待子进程结束,再执行父进程
  14.     p.join()
  15.     print("父进程结束---%d"%(num))
复制代码


进程间的“通讯”,利用到队列,数据原则是先进先出,后进后出。你用一个进程去产生某些数据,并存早列队里面,另外一个进程往这个列队取数据,实现进程之间的“通讯”
  1. from multiprocessing import Process,Queue
  2. import os,time
  3. def write(Q):
  4.     print("启动抓取子进程%s"%(os.getpid()))
  5.     for chr in ["A","B","C","D"]:
  6.         Q.put(chr)  #往队列传数据
  7.         time.sleep(1)
  8.     print("结束抓取子进程程%s" % (os.getpid()))

  9. def read(Q):
  10.     print("启动下载子进程%s"%(os.getpid()))
  11.     while True:
  12.         value = Q.get(True)  #没有数据,阻塞
  13.         print("value = ",value)
  14.     print("结束下载子进程%s" % (os.getpid()))

  15. if __name__ == '__main__':
  16.     #利用队列:由父进程创建队列,并传递给子进程,实现进程间的通讯
  17.     print("父进程启动")
  18.     q = Queue()
  19.     writ = Process(target=write,args=(q,))
  20.     rea = Process(target=read,args=(q,))
  21.     writ.start()
  22.     rea.start()
  23.     writ.join()
  24.     #rea进程里是个死循环,无法等待其结束 ,只能强行结束
  25.     rea.terminate()
  26.     print("父进程结束")
复制代码


多线程和多进程最大的不同在于,多进程中,同一个变量各自有一分拷贝存在每个进程中,互不影响
而多线程中,所有的变量都有所有线程共享。所以任何一个变量都可以被任意一个线程修改,
因此线程之间,共享数据最大的危险在于多个线程同时修改改一个变量,容易吧内容改乱。
如下代码当range大到一定数值,线程同时对数据修改,会产生不可估计的值。结果肯定不会为零
  1. from threading import Thread
  2. num = 0

  3. def run(n):
  4.     global num
  5.     for i in range(10):
  6.         num += n  #当线程同时执行到这里,num已经等于9,另外一个线程执行了 9 + 6 此时num=15
  7.         num -= n #这里执行就变成  15 - 6

  8. if __name__ == '__main__':
  9.     t1 = Thread(target=run,args=(6,))
  10.     t2 = Thread(target=run,args=(9,))
  11.     t1.start()
  12.     t2.start()
  13.     t1.join()
  14.     t2.join()

  15.     print("NUM =",num)
复制代码


线程锁解决数据混乱
  1. from threading import Thread,Lock
  2. #锁对象
  3. lock = Lock()

  4. num = 0
  5. def run(n):
  6.     global num
  7.     for i in range(10000000):
  8.         '''
  9.         # 加上线程锁
  10.         #确保线程锁中,只能有一个线程存在执行
  11.         #阻塞了多线程的并发执行,包含锁的某段代码实际上只能以单线程模式执行,所以效率消耗非常大
  12.         #由于存在多个锁,不同线程持有不同的锁,并试图获取其他的锁,可能造成死锁,导致多个线程挂起(被挡在锁外面,一直等待),只能靠系统强制终止
  13.         lock.acquire()
  14.         try:
  15.             num += n
  16.             num -= n
  17.         finally:
  18.         #释放线程锁
  19.             lock.release()
  20.         '''
  21.         #与上面代码功能相同,with lock ,可以自动上锁,与解锁
  22.         with lock:
  23.             num += n
  24.             num -= n

  25. if __name__ == '__main__':
  26.     t1 = Thread(target=run,args=(6,))
  27.     t2 = Thread(target=run,args=(9,))
  28.     t1.start()
  29.     t2.start()
  30.     t1.join()
  31.     t2.join()
  32.     print("NUM =",num)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-29 04:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表