当前位置: 首页 > news >正文

【Python】线程

目录

1. 线程的创建与销毁

2. 线程共享全局变量

3. 互斥锁

4. 进程和线程的对比


1. 线程的创建与销毁

        线程是进程的一个分支,进程默认有一个线程,但也可以有多个线程

        线程是CPU调度的基本单位

        线程是依附在进程里面的,由进程创建,没有进程就没有线程

        线程的模块:threading

        线程的运行是无序的

        主线程退出并不影响子线程的运行

        线程的参数与进程一样:Thread(group, target, name, args, kwargs)

        保护机制:join()

import threading
import os
import time

def ChildThread1(cnt):
    for i in range(cnt):
        print(f'{i} 这是第 1 个子线程, pid=', os.getpid())
        time.sleep(0.5)

def ChildThread2(cnt):
    for i in range(cnt):
        print(f'{i} 这是第 2 个子线程')
        time.sleep(0.5)

if __name__ == '__main__':
    # 创建子线程
    childThread1 = threading.Thread(target=ChildThread1, args=(6,))  # 用逗号区分元组和普通括号
    childThread2 = threading.Thread(target=ChildThread2, kwargs={'cnt': 6})

    # 运行子线程
    childThread1.start()
    childThread2.start()

    # 主线程代码
    for i in range(3):
        print('这是主线程, pid=', os.getpid())
        time.sleep(0.5)
    print('主进程循环结束')
    childThread1.join()
    for i in range(3):
        print('主进程等待线程完毕')
        time.sleep(1)

        

2. 线程共享全局变量

import threading

# 创建全局变量
g_cnt = 0

def Sum1():
    global g_cnt
    for i in range(2000000):
        g_cnt += 1
    print(f'Sum1: g_cnt = {g_cnt}')

def Sum2():
    global g_cnt
    for i in range(2000000):
        g_cnt += 1
    print(f'Sum2: g_cnt = {g_cnt}')

if __name__ == '__main__':
    childThread1 = threading.Thread(target=Sum1)
    childThread2 = threading.Thread(target=Sum2)

    childThread1.start()
    childThread2.start()

 

        由运行结果可得,线程之间可共享全局变量,且每次运行的结果都不一样

        由于全局变量在两个线程中来回切换,故两个线程得到的结果都一定大于等于循环数,小于等于总循环数

        限制全局变量的切换:1. 线程等待 join        2. 互斥锁 lock

3. 互斥锁

        当有线程开始执行任务前,先将全局变量锁定,不让其他的线程使用这个变量,当它执行完成后,再开锁,允许其他线程使用

        互斥锁的锁定和释放要搭配使用,上锁之后必须要释放

        每次只有一个线程可以获得锁,如果此时另一个线程试图获得锁,就必须进程阻塞等待那个正在被使用的锁被释放

        创建锁:lock = threadding.Lock()

        锁定:lock.acquire()

        释放:lock.release()

import threading

# 创建全局变量
g_cnt = 0

# 创建锁
lock = threading.Lock()

def Sum1():
    lock.acquire()
    global g_cnt
    for i in range(2000000):
        g_cnt += 1
    print(f'Sum1: g_cnt = {g_cnt}')
    lock.release()

def Sum2():
    lock.acquire()
    global g_cnt
    for i in range(2000000):
        g_cnt += 1
    print(f'Sum2: g_cnt = {g_cnt}')
    lock.release()

if __name__ == '__main__':
    childThread1 = threading.Thread(target=Sum1)
    childThread2 = threading.Thread(target=Sum2)

    childThread1.start()
    childThread2.start()

 

4. 进程和线程的对比

        进程之间不共享全局变量

        线程之间共享全局变量,要注意资源竞争问题,解决办法:互斥锁或者线程同步

        创建进程的资源开销比创建线程的资源开销大

        进程是操作系统分配资源的基本单位,线程是CPU调度的基本单位

        线程不能独立执行,必须依附在进程中

        多进程开发比单进程多线程开发稳定性更强

相关文章:

  • 【markdown】markdown语法进阶
  • 自动驾驶自主避障概况
  • php mysql网络考试系统dzkf8994
  • python干饭神器---今天吃什么?python告诉你
  • 华为OD机试题【打折买水果】用 C++ 编码,速通
  • 我用Python写的一个操控玩具车的程序
  • Springboot整合Nacos实现动态线程池
  • 软考中级到底有没有用?价值高吗?
  • java基础面试题(一)
  • 【算法题】831. 隐藏个人信息
  • arthas 源码分析 篇一 【结构篇】
  • HTML5 <abbr> 标签 和 HTML5 <applet> 标签
  • C++面向对象高级编程(上)
  • 安装和配置 Flask
  • Java --- 继承
  • 0基础学习移动端适配
  • DataBase in Android
  • Java 23种设计模式 之单例模式 7种实现方式
  • Map集合、散列表、红黑树介绍
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • Ruby 2.x 源代码分析:扩展 概述
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 力扣(LeetCode)357
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 如何用vue打造一个移动端音乐播放器
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 字符串匹配基础上
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 2017年360最后一道编程题
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #LLM入门|Prompt#3.3_存储_Memory
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #pragma预处理命令
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (done) 两个矩阵 “相似” 是什么意思?
  • (Matlab)使用竞争神经网络实现数据聚类
  • (二十四)Flask之flask-session组件
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (一)Dubbo快速入门、介绍、使用
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET BackgroundWorker
  • .Net 垃圾回收机制原理(二)
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • .NET中使用Protobuffer 实现序列化和反序列化