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

【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调度的基本单位

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

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


http://www.kler.cn/a/5112.html

相关文章:

  • Unity2D初级背包设计后篇 拓展举例与不足分析
  • C++ 多线程异步操作
  • 【简博士统计学习方法】第1章:2. 统计学习方法的基本分类
  • 【C++习题】20. 两个数组的交集
  • 运行vue项目,显示“npm”无法识别为 cmdlet、函数、脚本文件或可操作程序的名称
  • Matplotlib 直方图:数据可视化基础
  • java企业级信息系统开发学习笔记02初探spring——利用组件注解符精简spring配置文件
  • 第14章_MySQL事务日志
  • 2009年9月Java全国计算机等级考试二级笔试试卷
  • 可用的公开 RTSP/ RTMP 在线视频流资源地址(亲测可行)
  • python去掉字符串中的指定字符的方法
  • 《代码实例》Vue组件与路由
  • 蓝桥杯刷题冲刺 | 倒计时9天
  • 企业安全现状与未来趋势如何?
  • 软件测试方法下篇(正交法、场景设计法、错误猜测法)
  • Go工程基础知识
  • 论文阅读 | End-to-End Learning of Representations for Asynchronous Event-Based Data
  • Python轻量级Web框架Flask(2)——Flask模板渲染/Flask项目拆分
  • Intel Pin常用基础函数
  • Java设计模式-7、装饰器模式
  • 【华为OD机试真题JAVA】两个数和两数之和绝对值问题
  • BO OLAP 连接 HANA 先决条件
  • 【SSM】MyBatis(十一.MyBatis的高级映射和延迟加载)
  • 设计模式——装饰者模式
  • satellite.js库下载、介绍、安装、引用,返回函数的方法
  • chatgpt-retrieval-plugin:chatgpt检索插件简介