1. 线程的注意点介绍

  1. 线程之间执行是无序的
  2. 主线程会等待所有的子线程执行结束再结束
  3. 线程之间共享全局变量
  4. 线程之间共享全局变量数据出现错误问题

2. 线程之间执行是无序的

import threading
import timedef task():time.sleep(1)print("当前线程:", threading.current_thread().name)if __name__ == '__main__':for _ in range(5):sub_thread = threading.Thread(target=task)sub_thread.start()

执行结果:

说明:

  • 线程之间执行是无序的,它是由cpu调度决定的 ,cpu调度哪个线程,哪个线程就先执行,没有调度的线程不能执行。
  • 进程之间执行也是无序的,它是由操作系统调度决定的,操作系统调度哪个进程,哪个进程就先执行,没有调度的进程不能执行。

3. 主线程会等待所有的子线程执行结束再结束

假如创建一个子线程,这个子线程执行完大概需要2.5秒钟,现在让主线程执行1秒钟就退出程序,查看一下执行结果,示例代码如下:

import threading
import time# 测试主线程是否会等待子线程执行完成以后程序再退出
def show_info():for i in range(5):print("test:", i)time.sleep(0.5)if __name__ == '__main__':sub_thread = threading.Thread(target=show_info)sub_thread.start()# 主线程延时1秒time.sleep(1)print("over")

执行结果:

说明:

通过上面代码的执行结果,可以得知: 主线程会等待所有的子线程执行结束再结束

假如就让主线程执行1秒钟,子线程就销毁不再执行,那怎么办呢?

  • 可以设置守护主线程

守护主线程:

  • 守护主线程就是主线程退出子线程销毁不再执行

设置守护主线程有两种方式:

  1. threading.Thread(target=show_info, daemon=True)
  2. 线程对象.setDaemon(True)

设置守护主线程的示例代码:

import threading
import time# 测试主线程是否会等待子线程执行完成以后程序再退出
def show_info():for i in range(5):print("test:", i)time.sleep(0.5)if __name__ == '__main__':# 创建子线程守护主线程 # daemon=True 守护主线程# 守护主线程方式1sub_thread = threading.Thread(target=show_info, daemon=True)# 设置成为守护主线程,主线程退出后子线程直接销毁不再执行子线程的代码# 守护主线程方式2# sub_thread.setDaemon(True)sub_thread.start()# 主线程延时1秒time.sleep(1)print("over")

执行结果:

4. 线程之间共享全局变量

示例需求:

  1. 定义一个列表类型的全局变量
  2. 创建两个子线程分别执行向全局变量添加数据的任务和向全局变量读取数据的任务
  3. 查看线程之间是否共享全局变量数据
import threading
import time# 定义全局变量
my_list = list()# 写入数据任务
def write_data():for i in range(5):my_list.append(i)time.sleep(0.1)print("write_data:", my_list)# 读取数据任务
def read_data():print("read_data:", my_list)if __name__ == '__main__':# 创建写入数据的线程write_thread = threading.Thread(target=write_data)# 创建读取数据的线程read_thread = threading.Thread(target=read_data)write_thread.start()# 延时# time.sleep(1)# 主线程等待写入线程执行完成以后代码在继续往下执行write_thread.join()print("开始读取数据啦")read_thread.start()

执行结果:

5. 线程之间共享全局变量数据出现错误问题

示例需求:

  1. 定义两个函数,实现循环100万次,每循环一次给全局变量加1
  2. 创建两个子线程执行对应的两个函数,查看计算后的结果
import threading# 定义全局变量
g_num = 0# 循环一次给全局变量加1
def sum_num1():for i in range(1000000):global g_numg_num += 1print("sum1:", g_num)# 循环一次给全局变量加1
def sum_num2():for i in range(1000000):global g_numg_num += 1print("sum2:", g_num)if __name__ == '__main__':# 创建两个线程first_thread = threading.Thread(target=sum_num1)second_thread = threading.Thread(target=sum_num2)# 启动线程first_thread.start()# 启动线程second_thread.start()

执行结果:

注意点:

        多线程同时对全局变量操作数据发生了错误

错误分析:

两个线程first_thread和second_thread都要对全局变量g_num(默认是0)进行加1运算,但是由于是多线程同时操作,有可能出现下面情况:

  1. 在g_num=0时,first_thread取得g_num=0。此时系统把first_thread调度为”sleeping”状态,把second_thread转换为”running”状态,t2也获得g_num=0
  2. 然后second_thread对得到的值进行加1并赋给g_num,使得g_num=1
  3. 然后系统又把second_thread调度为”sleeping”,把first_thread转为”running”。线程t1又把它之前得到的0加1后赋值给g_num。
  4. 这样导致虽然first_thread和first_thread都对g_num加1,但结果仍然是g_num=1

全局变量数据错误的解决办法:

线程同步: 保证同一时刻只能有一个线程去操作全局变量

同步: 就是协同步调,按预定的先后次序进行运行。如:你说完,我再说, 好比现实生活中的对讲机

线程同步的方式:

  1. 线程等待(join)
  2. 互斥锁

线程等待的示例代码:

import threading# 定义全局变量
g_num = 0# 循环1000000次每次给全局变量加1
def sum_num1():for i in range(1000000):global g_numg_num += 1print("sum1:", g_num)# 循环1000000次每次给全局变量加1
def sum_num2():for i in range(1000000):global g_numg_num += 1print("sum2:", g_num)if __name__ == '__main__':# 创建两个线程first_thread = threading.Thread(target=sum_num1)second_thread = threading.Thread(target=sum_num2)# 启动线程first_thread.start()# 主线程等待第一个线程执行完成以后代码再继续执行,让其执行第二个线程# 线程同步: 一个任务执行完成以后另外一个任务才能执行,同一个时刻只有一个任务在执行first_thread.join()# 启动线程second_thread.start()

执行结果:

python线程的注意点(线程之间执行是无序的、主线程会等待所有的子线程执行结束再结束(守护主线程)、线程之间共享全局变量、线程之间共享全局变量数据出现错误问题(线程等待(join)、互斥锁))相关推荐

  1. python进程的注意点(进程之间不共享全局变量、主进程会等待所有的子进程执行结束再结束)

    1. 进程的注意点介绍 进程之间不共享全局变量 主进程会等待所有的子进程执行结束再结束 2. 进程之间不共享全局变量 import multiprocessing import time# 定义全局变 ...

  2. Java多线程之----主线程会等待子线程结束再结束么,怎么让主线程等待子线程结束呐?

    首先给出结论: 主线程和子线程之间没有谁先谁后结束这种关联,它们只是各自负责自己的线程任务,如果该线程的任务结束了,该线程自然会结束运行. talk is cheap,show me the code ...

  3. 线程同步互斥机制--互斥锁

    目录 前言 一.互斥锁是什么? 二.互斥锁的使用 三.代码实现过程 1.初始化互斥锁 2.互斥锁上锁 3.互斥锁解锁 4.互斥锁释放 5.代码示例 四.死锁 前言 线程通信只需要操作共享的进程数据段即 ...

  4. linux网络编程之posix 线程(三):posix 匿名信号量与互斥锁 示例生产者--消费者问题

    http://blog.csdn.net/jnu_simba/article/details/9123603 一.posix 信号量 信号量的概念参见这里.前面也讲过system v 信号量,现在来说 ...

  5. l2tp连接尝试失败 因为安全层在初始化_线程安全互斥锁

    1认知 线程安全机制: 由于线程它是共享进程里面所有的资源,当然这里面就会包括虚拟内存里面所有的东西(包含全局变量,堆内存,映射的内存及程序段落等),它也继承了进程当中所有的资源(文件描述符,信号资源 ...

  6. linux进程线程同步之 - POSIX线程互斥锁

    POSIX线程互斥锁 使用范围:线程同步 本文转自:http://blog.csdn.net/jiebaoabcabc/article/details/37914769 一.函数介绍 1.初始化互斥锁 ...

  7. python多线程锁_Python多线程互斥锁使用

    # 代码 # coding=utf-8 """通过使用互斥锁,锁定全局变量,防止数据异常""" import threading num = ...

  8. LiteOS内核教程05 | 互斥锁(共享资源保护)

    上百篇原创人工智能系列教程,从理论到实战,手把手带你掌握人工智能,点击☞这里☜进入传送门~ 1. LiteOS的互斥锁 1.1. 互斥锁 在多任务环境下,往往存在多个任务竞争同一共享资源的应用场景,互 ...

  9. 正确使用锁保护共享数据,协调异步线程

    JMQ为提升性能,使用近乎无锁的设计: MQ中的锁是个必须使用的技术 使用锁会降低系统性能 如何正确使用锁? 异步和并发设计可大幅提升性能,但程序更复杂:多线程执行时,充斥不确定性.对一些需并发读写的 ...

最新文章

  1. 岭南六少个人独立博客开通啦
  2. 命令行选项解析函数:getopt()
  3. 成功解决 from ._conv import register_converters as _register_converters
  4. 微软11月份安全补丁更新 最高级别:重要
  5. [九]RabbitMQ-客户端源码之Consumer
  6. 精简JRE第一步 — 精简bin目录
  7. ubuntu安装配置elasticSearch(vagrant)
  8. vue父子组件传值之异步之后子组件无法拿到父组件传的值
  9. 货币制度 - 异想天开
  10. u盘服务器安装win7系统安装教程视频教程,小白U盘安装win7系统教程
  11. 预测房价实验-房价数据集
  12. PHP利用qq邮箱发邮件
  13. Apple HomeKit
  14. linux文件系统与模型【笔记】 surper block/inode/dentry/file
  15. 8年测开经验面试28K公司后,吐血整理出1000道高频面试题和答案
  16. iOS — 百度地图 使用
  17. js将html转为word文档,js将html导出到word文档(含echarts图表)
  18. 【原创】基于TensorFlow2识别人是否配戴眼镜的研究
  19. 吉林大学计算机软件工程考研经验 QA
  20. 【HTTP Live Streaming】(二)HLS 架构 部署 - 梳理

热门文章

  1. 想学Python?快看看这个教程!收藏!
  2. 联手中科大、浙大、华科大等高校,阿里研发4项最新AI安全技术
  3. 每年节省170万美元的文档预览费用,借助机器学习的DropBox有多强​?
  4. 员工培训:如何制定以数据为依据的业务决策
  5. 拼命学的编程,你却可能错过一个亿!
  6. ​我国科学家成功研制全球神经元规模最大的类脑计算机
  7. 腾讯AI Lab负责人张潼离职,张正友或接替其位
  8. 大家都收藏了的最新开源项目Top12!CV、NLP、机器学习一应俱全
  9. Yann LeCun力挺前AAAI主席,批判深度学习的Marcus遭怒怼
  10. 为什么不建议用try catch处理异常?