1 单进程单线程:一个人在一个桌子上吃菜。
2 单进程多线程:多个人在同一个桌子上一起吃菜。
3 多进程单线程:多个人每个人在自己的桌子上吃菜。

多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。

二、线程

threading是用来提供在一个进程内实现多线程的编程模块.

前面我们学习了多进程编程.

完成多任务, 也可以在一个进程内使用多个线程. 一个进程至少包括一个线程, 这个线程我们称之为主线程. 在主线程中开启的其他线程我们称之为子线程.

一个进程内的所有线程之间可以直接共享资源, 所以线程间的通信要比进程间通信方便了很多.

python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用

单线程示例:

import timedef say_sorry():print("亲爱的,我错了,我能吃饭了吗?")time.sleep(1)if __name__ == "__main__":for i in range(5):say_sorry()

多线程示例:

import threading
import timedef say_sorry():print("亲爱的,我错了,我能吃饭了吗?")time.sleep(1)if __name__ == "__main__":for i in range(5):t = threading.Thread(target=say_sorry)t.start() #启动线程,即让线程开始执行

说明:

  1. 可以明显看出使用了多线程并发的操作,花费时间要短很多
  2. 创建好的线程,需要调用start()方法来启动

2.1 threading

Python3 线程中常用的两个模块为:

  • _thread

    thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python3 中不能再使用"thread" 模块。为了兼容性,Python3 将 thread 重命名为 "_thread"

  • threading(推荐使用)

    threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

2.2 Thread类

Thread类表示在单独的控制线程中运行的活动。有两种方法可以指定这种活动:

2.2.1、给构造函数传递回调对象

mthread=threading.Thread(target=xxxx,args=(xxxx))
mthread.start()

2.2.2、在子类中重写run() 方法  这里举个小例子:

import threading
import time
class MyThread(threading.Thread):def __init__(self,arg):super(MyThread, self).__init__()#注意:一定要显式的调用父类的初始化函数。self.arg=argdef run(self):#定义每个线程要运行的函数time.sleep(1)print('the arg is:%s\r' % self.arg)for i in range(4):t =MyThread(i)t.start()print('main thread end!')

2.2.3、多线程之间共享全局变量

​ 多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响, 而多线程中,所有变量都由所有线程共享,下面观察一下两条线程中共享同一份数据。

from threading import Thread
import time g_num = 100        # 定义全局变量g_numdef work1():num = 1       # 定义局部变量numglobal g_num     # 关键字global标记全局变量g_numfor i in range(3):g_num += 1        # 更改全局变量的值print("---子线程1---work1函数---g_num:%d" % g_num)def work2():num = 2global g_num       # 关键字global标记全局变量g_numprint("\t---子线程2---work2函数---个g_num:%d" % g_num)if __name__ == "__main__":print("启动线程之前:g_num:%d" % g_num)t1 = Thread(target=work1)    # 创建t1子线程,分配任务work1t2 = Thread(target=work2)    # 创建t2子线程,分配任务work2t1.start()     # 启动t1线程time.sleep(1)   # 等待t1线程执行完毕,观察t2线程中打印的全局变量是否发生改变t2.start()      # 启动t2线程

2.2.4、全局变量作为参数传递

将列表作为参数传递进来,在参数末尾追加元素

from threading import Thread
import timeg_list = [10, 20, 30]def work1(list):for i in range(3):list.append(i)    # 更改参数的值,在列表末尾追加元素print("--子线程1--work1----num:", list)def work2(list):print("\t--子线程2---work2---num:", list)if __name__ == "__main__":print("主线程访问g_list:" , g_list)t1 = Thread(target=work1, args=(g_list,))    # 创建线程t1 将g_list作为参数传递进去 执行函数work1t2 = Thread(target=work2, args=(g_list,))    # 创建线程t2 将g_list作为参数传递进去 执行函数work2t1.start()time.sleep(1)t2.start()

将列表作为参数传递进来,将参数重置

from threading import Thread
import timeg_list = [10, 20 ,30]def work1(list):for i in range(3):# list.append(i)list = [1, 2, 3]    # 重置参数print("--子线程1--work1----num:", list)def work2(list):print("\t--子线程2---work2---num:", list)if __name__ == "__main__":print("主线程访问g_list:" , g_list)t1 = Thread(target=work1, args=(g_list,))   # 创建线程t1 将g_list作为参数传递进去 执行函数work1t2 = Thread(target=work2, args=(g_list,))  # 创建线程t2 将g_list作为参数传递进去 执行函数work2t1.start()  time.sleep(1)t2.start()

2.2.5、线程的锁

​ 多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。

来看看多个线程同时操作一个变量怎么把内容给改乱了:

import time, threading# 假定这是你的银行存款:
balance = 0def change_it(n):# 先存后取,结果应该为0:global balancebalance = balance + nbalance = balance - ndef run_thread(n):for i in range(100000):change_it(n)if __name__ == "__main__":t1 = threading.Thread(target=run_thread, args=(5,))t2 = threading.Thread(target=run_thread, args=(8,))t1.start()t2.start()t1.join()t2.join()print(balance)

​ 每次执行的结果不一定是个啥,究其原因,是因为修改balance需要多条语句,而执行这几条语句时,线程可能中断,从而导致多个线程把同一个对象的内容改乱了。

​ 两个线程同时一存一取,就可能导致余额不对,你肯定不希望你的银行存款莫名其妙地变成了负数,所以,我们必须确保一个线程在修改balance的时候,别的线程一定不能改。

​ 如果我们要确保balance计算正确,就要给change_it()上一把锁,当某个线程开始执行change_it()时,我们说,该线程因为获得了锁,因此其他线程不能同时执行change_it(),只能等待,直到锁被释放后,获得该锁以后才能改。由于锁只有一个,无论多少线程,同一时刻最多只有一个线程持有该锁,所以,不会造成修改的冲突。创建一个锁就是通过threading.Lock()来实现:

#锁的使用
mutex = threading.Lock()  #创建锁
mutex.acquire([timeout])  #锁定
mutex.release()  #释放
import time, threadingbalance = 0
lock = threading.Lock()def change_it(n):# 先存后取,结果应该为0:global balancebalance = balance + nbalance = balance - ndef run_thread(n):for i in range(100000):# 先要获取锁:lock.acquire()try:# 放心地改吧:change_it(n)finally:# 改完了一定要释放锁:lock.release() if __name__ == "__main__":t1 = threading.Thread(target=run_thread, args=(5,))t2 = threading.Thread(target=run_thread, args=(8,))t1.start()t2.start()t1.join()t2.join()print(balance)

很多人现在还不知道的知识点,Python多进程和多线程详解!相关推荐

  1. 你所不知道的console.log()(console.log详解)

    console.log,作为一个前端开发者,想必每天都会用它来做分析调试,但这个简单函数背后你所不知道的一面,很多人未必使用过,有一些也是很方便使用的 基础 首先,简单科普这个函数的作用.前端开发者可 ...

  2. Python之多进程和多线程详解

    1.进程的概念 一个CPU的时候运行,轮询调度实现并发执行 多CPU运行机制: 计算机程序:存储在磁盘上的可执行二进制(或其他类型)文件. 只有把它们加载到内存中,并被操作系统调用它们才会拥有其自己的 ...

  3. python多进程队列中的队列_python 多进程队列数据处理详解

    我就废话不多说了,直接上代码吧! # -*- coding:utf8 -*- import paho.mqtt.client as mqtt from multiprocessing import P ...

  4. 射频混频器matlab,一个很多射频/天线工程师不知道的神奇网站

    [[一只射频攻城狮]一个很多射频/天线工程师不知道的神奇网站]https://toutiao.com/group/6858648754199724551/?app=explore_article&am ...

  5. 网络运维与安全岗位月薪2.5w,您还不知道的前景!

    网络运维与安全岗位月薪2.5w,您还不知道的前景! 一.为什么学网络安全?标重点 1..市场巨大 每年各安全厂商收入高达400亿左右,随着5G的发展,万物互联时代,市场将进一步扩大. 2..薪资高 网 ...

  6. 【Android】你可能还不知道的elevation、以及Z值等

    Android你可能还不知道的elevation以及Z值等 elevation以及Z值是什么 有什么用处呢 影响View的阴影 影响View相互阻挡顺序 还有CardView [Android]你可能 ...

  7. 环境变了,很多人却还没意识到。。

    阅读本文大概需要 3.1 分钟. 2019 开年相信大家就听到一些不太乐观的消息了,如: 滴滴宣布裁员 15% 涉及员工超 2000 人. 京东宣布 2019 年将末位淘汰 10% 的副总裁级别以上的 ...

  8. android 签名包闪退,解决APP连续闪退的方案,你还不知道的签名方式

    原标题:解决APP连续闪退的方案,你还不知道的签名方式 用户在使用APP检测到连续闪退后,接下来要尝试对闪退进行修复,这里先分析可能的闪退原因: 闪退原因 连续闪退,可能是 App 启动关键路径中执行 ...

  9. 一文看懂Python多进程与多线程编程(工作学习面试必读)

    进程(process)和线程(thread)是非常抽象的概念, 也是程序员必需掌握的核心知识.多进程和多线程编程对于代码的并发执行,提升代码效率和缩短运行时间至关重要.小编我今天就来尝试下用一文总结下 ...

最新文章

  1. pytorch 单机多卡训练distributedDataParallel
  2. python整理数据_Python常见数据结构整理
  3. 在行列都排好序的矩阵中找数
  4. SQL注入攻击实现原理与攻击过程详解
  5. Struts result param详细设置
  6. 企业要顺应社会生态环境
  7. 文献记录(part3)--Clusterpath An Algorithm for Clustering using Convex Fusion Penalties
  8. python定义_python __xx__的定义和用处
  9. 数论基础之组合数计数问题
  10. java下载好怎么验证_Java JDK下载、安装和验证
  11. python零基础学习书-零基础如何学好python?推荐6本入门书籍,帮你打基础
  12. 【codevs1220】数字三角形
  13. Spring框架零基础学习(一):IOC|DI、AOP
  14. 优化服务器犯法吗,服务器稳定性对于SEO优化有什么影响
  15. linux下实现getch()函数的功能,Linux下实现getch()函数功能
  16. canvas教程16-滚动的车轮
  17. 浙江移动智能语音服务器,电视还能这样玩?中国移动智能语音遥控器,让电视机听你的...
  18. Java并发原理解析!docker命令
  19. JAVA 双亲委派机制
  20. 透明小电视上线——GitHub 热点速览 v.21.05

热门文章

  1. python-面向对向编程-小结
  2. 查询某个条件在一个区间内的数据
  3. 网站登录JWT的实现
  4. javascript将base64编码的图片数据转换为file并提交
  5. Winform中用了皮肤控件之后,报错:容量超出了最大容量 参数名:capacity
  6. 搭建PC架构的ISCSI存储系统
  7. 如何写出好的Java代码?
  8. jsp 页面中文乱码解决(笔记)
  9. 写在2009年的开始
  10. 面试官系统精讲Java源码及大厂真题 - 19 LinkedBlockingQueue 源码解析