并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)

并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的

线程

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

基本线程调用实例:

  1. import time
  2. import threading
  3.  
  4. def dancing():
  5. for i in range(1, 4):
  6. print('跳舞中%d' % i)
  7. time.sleep(0.5)
  8. print('dancing 线程结束')
  9.  
  10. def singing():
  11. for i in range(1, 5):
  12. print('唱歌中%d' % i)
  13. time.sleep(0.5)
  14. print('singing 线程结束')
  15.  
  16. def main():
  17. # 创建子线程对象
  18. t1 = threading.Thread(target=dancing)
  19. t2 = threading.Thread(target=singing)
  20. # 子线程开始执行
  21. t1.start()
  22. t2.start()
  23. # 查看正在运行的子线程数量
  24. while True:
  25. length = len(threading.enumerate())
  26. print('当前运行的线程数为:%d' % length)
  27. if length <= 1:
  28. break
  29. time.sleep(0.2)
  30.  
  31. if __name__ == '__main__':
  32. main()

继承Thread类自定义类调用实例:

  1. import threading
  2. import time
  3.  
  4. class DancingThread(threading.Thread):
  5. def run(self):
  6. for i in range(1, 3):
  7. print('线程名:%s,正在跳舞:。。。%d' % (self.name, i))
  8. time.sleep(0.5)
  9. print('\n跳舞线程结束')
  10.  
  11. class SingingThread(threading.Thread):
  12. def run(self):
  13. for i in range(1, 5):
  14. print('线程名:%s,正在唱歌:。。。%d' % (self.name, i))
  15. time.sleep(0.5)
  16. print('唱歌线程结束')
  17.  
  18. def main():
  19. # 创建Thread对象
  20. dancing = DancingThread()
  21. sing = SingingThread()
  22. # 调用run方法,开启线程
  23. dancing.start()
  24. sing.start()
  25.  
  26. if __name__ == '__main__':
  27. main()

线程共享全局变量

  • 在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据
  • 缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)
  • 假设两个线程t1和t2都要对全局变量g_num(默认是0)进行加1运算,t1和t2都各对g_num加10次,g_num的最终的结果应该为20。
  • 但是由于是多线程同时操作,有可能出现下面情况:
    1. 在g_num=0时,t1取得g_num=0。此时系统把t1调度为”sleeping”状态,把t2转换为”running”状态,t2也获得g_num=0
    2. 然后t2对得到的值进行加1并赋给g_num,使得g_num=1
    3. 然后系统又把t2调度为”sleeping”,把t1转为”running”。线程t1又把它之前得到的0加1后赋值给g_num。
    4. 这样导致虽然t1和t2都对g_num加1,但结果仍然是g_num=1
  1. import threading
  2. import time
  3.  
  4. g_num = 0
  5.  
  6. class DancingThread(threading.Thread):
  7. def __init__(self, num):
  8. threading.Thread.__init__(self)
  9. self.num = num
  10.  
  11. def run(self):
  12. global g_num
  13. for i in range(self.num):
  14. g_num += 1
  15. print('跳舞线程结束,g_num:%d' % g_num)
  16.  
  17. class SingingThread(threading.Thread):
  18. def __init__(self, num):
  19. threading.Thread.__init__(self)
  20. self.num = num
  21.  
  22. def run(self):
  23. global g_num
  24. for i in range(self.num):
  25. g_num += 1
  26. print('唱歌线程结束,g_num:%d' % g_num)
  27.  
  28. def main():
  29. # 创建Thread对象
  30. dancing = DancingThread(1000000)
  31. sing = SingingThread(1000000)
  32. # 调用run方法,开启线程
  33. print('初始g_num: %d' % g_num)
  34. dancing.start()
  35. sing.start()
  36. # 等待子线程运行完
  37. while len(threading.enumerate()) > 1:
  38. time.sleep(1)
  39. print('线程结束后g_num: %d' % g_num)
  40.  
  41. if __name__ == '__main__':
  42. main()

运行结果为:

  1. 初始g_num: 0
  2. 跳舞线程结束,g_num1292807
  3. 唱歌线程结束,g_num1712212
  4. 线程结束后g_num: 1712212

使用互斥锁解决线程冲突

  1. # 创建锁
  2. mutex = threading.Lock()
  3. # 锁定
  4. mutex.acquire()
  5. # 释放
  6. mutex.release()
  1. import time
  2. import threading
  3. g_num = 0
  4.  
  5. def dancing(num, mutex):
  6. global g_num
  7. for i in range(num):
  8. # 上锁
  9. mutex.acquire()
  10. # 计算
  11. g_num += num
  12. # 解锁
  13. mutex.release()
  14.  
  15. print('dancing 线程结束,num值: %d' % g_num)
  16.  
  17. def singing(num, mutex):
  18. global g_num
  19. for i in range(num):
  20. # 上锁
  21. mutex.acquire()
  22. # 计算
  23. g_num += num
  24. # 解锁
  25. mutex.release()
  26.  
  27. print('dancing 线程结束,num值: %d' % g_num)
  28.  
  29. def main():
  30. print('初始值:%d' % g_num)
  31. # 创建锁对象
  32. mutex = threading.Lock()
  33. # 创建子线程对象
  34. t1 = threading.Thread(target=dancing, args=(1000000, mutex, ))
  35. t2 = threading.Thread(target=singing, args=(1000000, mutex, ))
  36. # 子线程开始执行
  37. t1.start()
  38. t2.start()
  39.  
  40. if __name__ == '__main__':
  41. main()

运行结果:

  1. 初始值:0
  2. dancing 线程结束,num值: 1876392000000
  3. dancing 线程结束,num值: 2000000000000

python-多任务编程01-线程(threading)的更多相关文章

  1. Python高级——多任务编程之线程

    转: Python高级--多任务编程之线程 文章目录 线程概念 1. 线程的介绍 2. 线程的概念 3. 线程的作用 多线程的使用 1. 导入线程模块 2. 线程类Thread参数说明 3. 启动线程 ...

  2. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...

  3. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块

    本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...

  4. python并发编程之线程/协程

    python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...

  5. Python并发编程01 /操作系统发展史、多进程理论

    Python并发编程01 /操作系统发展史.多进程理论 目录 Python并发编程01 /操作系统发展史.多进程理论 1. 操作系统 2. 进程理论 1. 操作系统 定义:管理控制协调计算机中硬件与软 ...

  6. python网络编程01 /C/S架构|B/S架构、网络通信原理、五层协议、七层协议简述、端口映射技术

    python网络编程01 /C/S架构|B/S架构.网络通信原理.五层协议.七层协议简述.端口映射技术 目录 python网络编程01 /C/S架构|B/S架构.网络通信原理.五层协议.七层协议简述. ...

  7. Python网络编程(线程通信、GIL、服务器模型)

    什么是进程.进程的概念? 进程的概念主要有两点: 第一,进程是一个实体.每一个进程都有它自己的地址空间, 一般情况下,包括文本区域(text region).数据区域(data region)和堆栈( ...

  8. python网络编程-01

    python网络编程 1.socket模块介绍 ①在网络编程中的一个基本组件就是套接字(socket),socket是两个程序之间的“信息通道”. ②套接字包括两个部分:服务器套接字.客户机套接字 ③ ...

  9. python成长之路【第十一篇】:网络编程之线程threading模块

    一.threading模块介绍 threading 模块建立在 _thread 模块之上.thread 模块以低级.原始的方式来处理和控制线程,而 threading 模块通过对 thread 进行二 ...

  10. Python并发编程-进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

随机推荐

  1. 利用xampp集成环境搭建pikachu靶场及部分问题解决

    xampp的环境部署 1.本地服务器的搭建 首先要到官网下载xampp https://www.apachefriends.org/zh_cn/index.html 有各个不同的系统版本,这里我们选择 ...

  2. 3dTiles 数据规范详解[2] Tileset与Tile

    转载请声明出处:全网@秋意正寒 https://www.cnblogs.com/onsummer/p/13128682.html 一.一个简单的3dTiles数据示例 上图是一份 3dTiles数据集 ...

  3. DOM-BOM-EVENT(5)

    5.宽.高.位置相关 5.1.clientX/clientY clientX和clientY表示鼠标在浏览器可视区的坐标位置 <script> document.onclick = fun ...

  4. SpringBoot2.x入门:快速创建一个SpringBoot应用

    前提 这篇文章是<SpringBoot2.x入门>专辑的第2篇文章,使用的SpringBoot版本为2.3.1.RELEASE,JDK版本为1.8. 常规的套路会建议使用Spring官方提 ...

  5. 从零创建发布属于自己的composer包

    原文地址:https://www.wjcms.net/archives/从零创建发布属于自己的composer包 今天给大家讲解一下如何从零创建发布属于自己的composer包. composer包用 ...

  6. 状压DP之Mixed Up Cows G

    题目 传送们 大意 约翰家有N头奶牛,第i头奶牛的编号是Si,每头奶牛的编号都是唯一的.这些奶牛最近 在闹脾气,为表达不满的情绪,她们在挤奶的时候一定要排成混乱的队伍.在一只混乱的队 伍中,相邻奶牛的 ...

  7. 推荐一款Python开源库,技术人必备的造数据神器!

    1. 背景 在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,要么需要手动制造一些数据.由于现在的业务系统数据多种多样,千变万化.在手动制造数据的 ...

  8. postman-7-前置请求脚本

    前面讲了,tests初如何校验请求之后返回值是否正确 那前置脚本,就是处理,请求之前接口该如何处理,什么时候会用到呢? 比如:接口字段time,需要填入时间,而且这个是需要当前时间的,: 需要达到自动 ...

  9. Mybatis插件扩展以及与Spring整合原理

    @ 目录 前言 正文 插件扩展 1. Interceptor核心实现原理 2. Mybatis的拦截增强 Mybatis与Spring整合原理 1. SqlSessionFactory的创建 2. 扫 ...

  10. (二)学习了解OrchardCore笔记——开篇:OrchardCore的中间件

    现在开始看Starpup的中间件.这是一个扩展方法app.UseOrchardCore() public void Configure(IApplicationBuilder app, IHostEn ...