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

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

线程

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

基本线程调用实例:

import time
import threading def dancing():
for i in range(1, 4):
print('跳舞中%d' % i)
time.sleep(0.5)
print('dancing 线程结束') def singing():
for i in range(1, 5):
print('唱歌中%d' % i)
time.sleep(0.5)
print('singing 线程结束') def main():
# 创建子线程对象
t1 = threading.Thread(target=dancing)
t2 = threading.Thread(target=singing)
# 子线程开始执行
t1.start()
t2.start()
# 查看正在运行的子线程数量
while True:
length = len(threading.enumerate())
print('当前运行的线程数为:%d' % length)
if length <= 1:
break
time.sleep(0.2) if __name__ == '__main__':
main()

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

import threading
import time class DancingThread(threading.Thread):
def run(self):
for i in range(1, 3):
print('线程名:%s,正在跳舞:。。。%d' % (self.name, i))
time.sleep(0.5)
print('\n跳舞线程结束') class SingingThread(threading.Thread):
def run(self):
for i in range(1, 5):
print('线程名:%s,正在唱歌:。。。%d' % (self.name, i))
time.sleep(0.5)
print('唱歌线程结束') def main():
# 创建Thread对象
dancing = DancingThread()
sing = SingingThread()
# 调用run方法,开启线程
dancing.start()
sing.start() if __name__ == '__main__':
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
import threading
import time g_num = 0 class DancingThread(threading.Thread):
def __init__(self, num):
threading.Thread.__init__(self)
self.num = num def run(self):
global g_num
for i in range(self.num):
g_num += 1
print('跳舞线程结束,g_num:%d' % g_num) class SingingThread(threading.Thread):
def __init__(self, num):
threading.Thread.__init__(self)
self.num = num def run(self):
global g_num
for i in range(self.num):
g_num += 1
print('唱歌线程结束,g_num:%d' % g_num) def main():
# 创建Thread对象
dancing = DancingThread(1000000)
sing = SingingThread(1000000)
# 调用run方法,开启线程
print('初始g_num: %d' % g_num)
dancing.start()
sing.start()
# 等待子线程运行完
while len(threading.enumerate()) > 1:
time.sleep(1)
print('线程结束后g_num: %d' % g_num) if __name__ == '__main__':
main()

运行结果为:

初始g_num: 0
跳舞线程结束,g_num:1292807
唱歌线程结束,g_num:1712212
线程结束后g_num: 1712212

使用互斥锁解决线程冲突

# 创建锁
mutex = threading.Lock()
# 锁定
mutex.acquire()
# 释放
mutex.release()
import time
import threading
g_num = 0 def dancing(num, mutex):
global g_num
for i in range(num):
# 上锁
mutex.acquire()
# 计算
g_num += num
# 解锁
mutex.release() print('dancing 线程结束,num值: %d' % g_num) def singing(num, mutex):
global g_num
for i in range(num):
# 上锁
mutex.acquire()
# 计算
g_num += num
# 解锁
mutex.release() print('dancing 线程结束,num值: %d' % g_num) def main():
print('初始值:%d' % g_num)
# 创建锁对象
mutex = threading.Lock()
# 创建子线程对象
t1 = threading.Thread(target=dancing, args=(1000000, mutex, ))
t2 = threading.Thread(target=singing, args=(1000000, mutex, ))
# 子线程开始执行
t1.start()
t2.start() if __name__ == '__main__':
main()

运行结果:

初始值:0
dancing 线程结束,num值: 1876392000000
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. 31_栈的分类.swf

    栈的分类: 栈可以分为静态栈和动态栈 静态栈:要删除先删除4才能删除3,以数组为数据结构 动态栈:以链表作为数据结构,在实际中使用动态栈比较多

  2. SpringBoot——项目启动时读取配置及初始化资源

    介绍   在开发过程中,我们有时候会遇到非接口调用而出发程序执行任务的一些场景,比如我们使用quartz定时框架通过配置文件来启动定时任务时,或者一些初始化资源场景等触发的任务执行场景. 方法一:注解 ...

  3. 学习Java的Day02

    知识点 数组: 一维数组   声明: 类型[] 数组名;([] 在前后没有影响,一般写在名称前.) 创建数组  数组名 =  new 类型[数组长度]. 数组索引从0开始.获取数组长度:数组名.len ...

  4. could not resolve property(无法解析属性)

    could not resolve property(无法解析属性) 顾名思义在写hql语句的时候,属性写错了! 请检查大小写,是实体类的,不是数据库表的! 一个一个检查,仔细看!

  5. (win7) 在IIS6.0 中配置项目

    1.进入IIS管理器 右击“计算机”->管理->服务和应用程序->Internet信息服务(IIS)管理器 2.将项目加入IIS中 网站->右击“默认网站”->添加虚拟目 ...

  6. 认识Eureka (F版)

    Spring Cloud 为开发者提供了在分布式系统中的一些常用的组件(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁定,决策竞选,分布式会话集群状态).使用Sprin ...

  7. 5000+字硬核干货!Redis 分布式集群部署实战

    原理: Redis集群采用一致性哈希槽的方式将集群中每个主节点都分配一定的哈希槽,对写入的数据进行哈希后分配到某个主节点进行存储. 集群使用公式(CRC16 key)& 16384计算键key ...

  8. 请解释ASP. NET中的web页面与隐藏类之间的关系

    请解释ASP.NET中的web页面与其隐藏类之间的关系 其实页面与其隐藏类之间就是一个部分类的关系,你在页面上放一个一个的控件就是在这个类中定义一个一个的属性, 因为是同一个类的部分类的关系,所以隐藏 ...

  9. 冷知识:达夫设备(Duff's Device)效率真的很高吗?

    ID:技术让梦想更伟大 作者:李肖遥 wechat链接:https://mp.weixin.qq.com/s/b1jQDH22hk9lhdC9nDqI6w 相信大家写业务逻辑的时候,都是面向if.el ...

  10. 帝国の狂欢(种树)(可撤销DP)

    题目描述 马上就要开学了!!! 为了给回家的童鞋们接风洗尘,HZOI帝国的老大决定举办一场狂欢舞会. 然而HZOI帝国头顶上的HZ大帝国十分小气,并不愿意给同学们腾出太多的地方.所以留给同学们开par ...