Python大数据之Python进阶(七)线程的注意点

news2024/9/21 2:41:52

线程的注意点

学习目标

  • 能够说出线程的注意点

1. 线程的注意点介绍

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

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

import threading
import time


def 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()Copy

执行结果:

当前线程: Thread-1
当前线程: Thread-2
当前线程: Thread-4
当前线程: Thread-5
当前线程: Thread-3Copy

说明:

  • 线程之间执行是无序的,它是由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")Copy

执行结果:

test: 0
test: 1
over
test: 2
test: 3
test: 4Copy

说明:

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

假如我们就让主线程执行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 守护主线程
    # 守护主线程方式1
    sub_thread = threading.Thread(target=show_info, daemon=True)
    # 设置成为守护主线程,主线程退出后子线程直接销毁不再执行子线程的代码
    # 守护主线程方式2
    # sub_thread.setDaemon(True)
    sub_thread.start()

    # 主线程延时1秒
    time.sleep(1)
    print("over")Copy

执行结果:

test: 0
test: 1
overCopy

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

需求:

  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()Copy

执行结果:

write_data: [0, 1, 2, 3, 4]
开始读取数据啦
read_data: [0, 1, 2, 3, 4]Copy

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

需求:

  1. 定义两个函数,实现循环100万次,每循环一次给全局变量加1
  2. 创建两个子线程执行对应的两个函数,查看计算后的结果
import threading

# 定义全局变量
g_num = 0


# 循环一次给全局变量加1
def sum_num1():
    for i in range(1000000):
        global g_num
        g_num += 1

    print("sum1:", g_num)


# 循环一次给全局变量加1
def sum_num2():
    for i in range(1000000):
        global g_num
        g_num += 1
    print("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()Copy

执行结果:

sum1: 1210949
sum2: 1496035Copy

注意点:

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

错误分析:

两个线程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

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

线程同步: 保证同一时刻只能有一个线程去操作全局变量 同步: 就是协同步调,按预定的先后次序进行运行。如:你说完,我再说, 好比现实生活中的对讲机

线程等待的示例代码:

import threading

# 定义全局变量
g_num = 0


# 循环1000000次每次给全局变量加1
def sum_num1():
    for i in range(1000000):
        global g_num
        g_num += 1

    print("sum1:", g_num)


# 循环1000000次每次给全局变量加1
def sum_num2():
    for i in range(1000000):
        global g_num
        g_num += 1
    print("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()Copy

执行结果:

sum1: 1000000
sum2: 2000000Copy

5. 小结

  • 线程执行执行是无序的

  • 主线程默认会等待所有子线程执行结束再结束,设置守护主线程的目的是主线程退出子线程销毁。

  • 线程之间共享全局变量,好处是可以对全局变量的数据进行共享。

  • 线程之间共享全局变量可能会导致数据出现错误问题,可以使用线程同步方式来解决这个问题。

    • 线程等待(join)

    进程和线程的对比

    学习目标

    • 能够知道进程和线程的关系

    1. 进程和线程的对比的三个方向

    1. 关系对比
    2. 区别对比
    3. 优缺点对比

    2. 关系对比

    1. 线程是依附在进程里面的,没有进程就没有线程。
    2. 一个进程默认提供一条线程,进程可以创建多个线程。

    image-20231009204843914

    2. 区别对比

    1. 进程之间不共享全局变量
    2. 线程之间共享全局变量,但是要注意资源竞争的问题,解决办法: 线程同步
    3. 创建进程的资源开销要比创建线程的资源开销要大
    4. 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
    5. 线程不能够独立执行,必须依存在进程中
    6. 多进程开发比单进程多线程开发稳定性要强

    3. 优缺点对比

    • 进程优缺点:
      • 优点:可以用多核
      • 缺点:资源开销大
    • 线程优缺点:
      • 优点:资源开销小
      • 缺点:不能使用多核

    4. 小结

    • 进程和线程都是完成多任务的一种方式
    • 多进程要比多线程消耗的资源多,但是多进程开发比单进程多线程开发稳定性要强,某个进程挂掉不会影响其它进程。
    • 多进程可以使用cpu的多核运行,多线程可以共享全局变量。
    • 线程不能单独执行必须依附在进程里面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1080718.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

17.(开发工具篇Gitlab)如何在Gitlab配置ssh key

前言: Git是分布式的代码管理工具,远程的代码管理是基于SSH的,所以要使用远程的Git则需要SSH的配置 一、git 配置 (1)打开 git 命令窗口 (2)配置用户名(填自己的姓名) git config --global user.name “chenbc” (3)配置用户邮箱(填自己的邮箱) git config …

有没有普通人也能赚钱的副业?挖漏洞兼职!

如何开展副业?网络安全月入过万! ​ 随着大数据和人工智能的兴起。各行业对信息安全和网络安全服务的需求量呈指数级的暴增。 这不最近,一个做运维的朋友在学网络安全。他告诉我,他靠挖漏洞赚钱上个月月入过万了,好香啊…

Unity 设置Inspect上问号的跳转链接

设置Inspect上问号的跳转链接 只需要在Class上添加特性:HelpURL即可!

《进化优化》第1章 绪论

文章目录 1.1 术语1.2 又一本关于进化算法的书1.3 先修课程1.4 家庭作业1.5 符号1.6 本书的大纲 1.1 术语 一些作者称进化算法为进化计算。另一些人称进化算法为基于种群的优化。一些作者称进化算法为计算机智能或计算智能。专家系统模仿演绎推理,进化算法则模仿归…

视频如何截取高清gif?高清gif一键制作

Gif动图表情包作为当下最受欢迎的一种图片格式,一般是在网上或是与友人的聊天中获取的。其实,制作gif动图的方法也很简单,一段视频就能够从中截取到很多gif动图。只需要使用gif动态图片制作(https://www.gif.cn/)工具&…

腾讯云上创建 对象存储cos

1. 登录腾讯云, 找到对象存储cos 2. 创建存储桶 3. 获取4个配置参数 桶名称 / 地域secretId / secretKey

若依以及flowbale达梦国产化数据库改造_全网最细

Springboot与flowable—达梦国产化改造 文章目录 Springboot与flowable—达梦国产化改造1、相关软件下载1.1 下载可视化工具 2 、源代码运行2.1 导入sql2.2 打开项目,导入pom依赖2.3 修改配置2.3.1 修改数据库配置2.3.2 修改redis配置2.3.3 运行后端2.3.4 运行前端 …

【SpringMVC篇】探索请求映射路径,Get请求与Post请求

🎊专栏【SpringMVC】 🍔喜欢的诗句:天行健,君子以自强不息。 🎆音乐分享【如愿】 🎄欢迎并且感谢大家指出小吉的问题🥰 文章目录 🌺请求映射路径⭐报错原因⭐解决方法 🌺…

OpenCV实现答题卡自动打分!

目录 1,主要原理以及函数介绍 全部代码,以 2 , 实现过程 3,结果展示 1,主要原理以及函数介绍 ap argparse.ArgumentParser() 创建一个ArgumentParser对象,并将其赋值给变量ap。这个对象可以接受我们的脚…

基于springboot实现教师人事档案管理系统项目【项目源码+论文说明】

基于springboot实现教师人事档案管理系统演示 摘要 教师人事档案管理系统理工作是一种繁琐的,务求准确迅速的信息检索工作。随着计算机信息技术的飞速发展,人类进入信息时代,社会的竞争越来越激烈,教师人事档案就越显示出其不可或…

JAVA开发者全家桶工具

一、前言 作为JAVA开发者,编码的时间其实只占平时工作的时间不到30%。作为项目管理和团队协作,平时处理的杂事其实很多,当然也是开发工作的一部分,比如写文档,任务管理,代码review、程序部署等等。这一节介…

墨西哥专线正清和双清包税有什么区别?

在国际贸易中,物流运输是一个至关重要的环节。对于从中国发往墨西哥的商品,物流公司通常会提供不同的运输方式和服务,如正清和双清包税等。那么,这两种方式有何不同呢? 首先,我们来看什么是“正清”和“双清”。 “正…

docker 登录本地仓库harbor问题

1、报错如下: 添加目标harbor 仓库的hosts vim /etc/hosts 2、报错如下: 添加修改/etc/docker/daemon.json文件中的 insecure-registries vim /etc/docker/daemon.json 然后 systemctl daemon-reload systemctl restart docker再次登录

【Hello Algorithm】暴力递归到动态规划(二)

暴力递归到动态规划(二) 背包问题递归版本动态规划 数字字符串改字母字符串递归版本动态规划 字符串贴纸递归版本动态规划 **特别需要注意的是 我们使用数组之前一定要进行初始化 不然很有可能会遇到一些意想不到的错误 比如说在Linux平台上 new出来的in…

易点易动让企业实现低值易耗品的智能化采购管理

对于企业而言,低值易耗品的采购和管理是一项重要的任务。然而,传统的采购管理方式往往繁琐且耗时,容易导致资源浪费和效率低下。为了解决这些问题,我们推出了易点易动采购管理系统,它以其高效、便捷和智能化的特点&…

怎样提取视频中的音频?分享一个一学就会的方法~

每次遇到视频中有好听的背景音乐都会想要保存下来,用于自己的视频创作。于是怎样单独提取视频中的音频部分就成了难题,今天教大家一个简单实用的视频提取音频办法,看完记得点赞收藏哦~ 第一步:打开【音分轨】APP&#…

论文精读-Semi-Supervised Classification with Graph Convolutional Networks

Semi-Supervised Classification with Graph Convolutional Networks 目录 Semi-Supervised Classification with Graph Convolutional Networks一、摘要介绍二、图上的快速近似卷积2.1 谱图卷积 (主要参考链接:[https://www.jianshu.com/p/35212baf6671…

100G SWDM4与100G BIDI SR光模块最新解决方案

随着数据中心和云计算网络的快速发展,高速度、高效率的数据传输需求不断增长。在这种背景下,100G SWDM4(短波分复用技术)和100G BIDI光模块作为两种先进的光模块技术,得到了广泛应用。下面我们来看看这两种光模块的应用…

基于Springboot实现垃圾分类网站管理系统项目【项目源码+论文说明】

基于Springboot实现垃圾分类网站管理系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个垃圾分类网站 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述垃…

Fiddler抓包常用功能介绍

Fiddler中常用的功能如下: 停止抓包清空会话窗内容过滤请求解码设置断点 一. 停止抓包 二. 清空会话窗 方法一,工具栏工具: 方法二,命令行形式: 当然,命令行工具也还支持其他命令的输入,这里不…