IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python 线程详解 -> 正文阅读

[Python知识库]python 线程详解

1、什么是线程?

线程:操作系统提供的抽象概念,是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。

2、python如何实现多线程?

python通常使用threading模块实现多线程,导入threading包,然后对象名= threading.Thread(target = 函数名) 创建线程对象,最后对象名.start() 创建线程。主要的线程方法:run(): 用以表示线程活动的方法;start():启动线程活动;join([time]): 等待至线程中止。

https://docs.python.org/zh-cn/3.8/library/threading.html?highlight=threading#module-threading

3、实现多线程?

import threading
import time


def task1(s):
    task_list = ['file1', 'file2', 'file3']
    for i in task_list:
        print('正在下载:{}'.format(i))
        time.sleep(s)
        print('下载成功:{}'.format(i))


def task2(s):
    task_list = ['music1', 'music2', 'music3', 'music4']
    for i in task_list:
        print('正在听音乐:{}'.format(i))
        time.sleep(s)


if __name__ == '__main__':
    t1 = threading.Thread(target=task1, args=(1,))  # 创建线程1
    t2 = threading.Thread(target=task2, args=(0.5,))  # 创建线程2
    t1.start()  # 启动线程
    t2.start()

4、全局解释器锁?

全局解释器锁(GIL)只允许1个Python线程控制Python解释器。这也就意味着同一时间点只能有1个Python线程运行。如果你的Python程序只有一个线程,那么全局解释器锁可能对你的影响不大,但是如果你的程序是CPU密集型同时使用了多线程,那么程序运行可能会受到很大影响。

Python为了能够支持多线程,而解决多线程之间数据完整性和状态同步的最简单方法就是加锁,所以在python创立之初默认加上了GIL。

具体可以参考:https://zhuanlan.zhihu.com/p/361695757

但是在python当中,当计算强度不高时,GIL默认会加上,但是当计算强度比较大的时候,GIL又会释放,下面两个例子说明。

(1)当计算强度不高时,由于有锁,所以数据并不会出错

import threading
import time
"""
两个线程共享一个全局变量,
每个线程都对变量进行操作,输出线程结束后的变量的值
"""
tacket = 1000


def task1():
    global tacket
    for i in range(0, 150):
        tacket -= 1


def task2():
    global tacket
    for i in range(0, 160):
        tacket -= 1


if __name__ == '__main__':
    t1 = threading.Thread(target=task1)
    t2 = threading.Thread(target=task2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print(tacket)


结果:
690

(2)当计算强度高时,锁被释放,所以数据出错

import threading
import time
"""
两个线程共享一个全局变量,
每个线程都对变量进行操作,输出线程结束后的变量的值
"""
tacket = 10000000


def task1():
    global tacket
    for i in range(0, 1500000):
        tacket -= 1


def task2():
    global tacket
    for i in range(0, 1600000):
        tacket -= 1


if __name__ == '__main__':
    t1 = threading.Thread(target=task1)
    t2 = threading.Thread(target=task2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print(tacket)

结果:
7217607

5、线程同步(加锁)

多线程的可以共享主线程的数据,在操作的时候可能会存在数据不同的问题解决办法是,加锁,锁 是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问,每次只能有一个线程对 Lock 对象加锁,线程在开始访问共享资源之前应先请求获得 Lock 对象。当对共享资源访问完成后,程序释放对 Lock 对象的锁定。

Python?的 threading 模块引入了锁(Lock)。threading 模块提供了 Lock 和 RLock 两个类,它们都提供了如下两个方法来加锁和释放锁:

  1. acquire(blocking=True, timeout=-1):请求对 Lock 或 RLock 加锁,其中 timeout 参数指定加锁多少秒。
  2. release():释放锁。

Lock 和 RLock 的区别如下:

  • threading.Lock:它是一个基本的锁对象,每次只能锁定一次,其余的锁请求,需等待锁释放后才能获取。
  • threading.RLock:它代表可重入锁(Reentrant Lock)。对于可重入锁,在同一个线程中可以对它进行多次锁定,也可以多次释放。如果使用 RLock,那么 acquire() 和 release() 方法必须成对出现。如果调用了 n 次 acquire() 加锁,则必须调用 n 次 release() 才能释放锁。

对线程进行加锁之后,计算结果就不会出错了?

import threading
import time
"""
两个线程共享一个全局变量,
每个线程都对变量进行操作,输出线程结束后的变量的值
"""
lock = threading.Lock()
tacket = 10000000


def task1():
    global tacket
    lock.acquire()
    for i in range(0, 1500000):
        tacket -= 1
    lock.release()


def task2():
    global tacket
    lock.acquire()
    for i in range(0, 1600000):
        tacket -= 1
    lock.release()


if __name__ == '__main__':
    t1 = threading.Thread(target=task1)
    t2 = threading.Thread(target=task2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print(tacket)

结果:
6900000

6、死锁

所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程

在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源时,就会造成死锁。尽管死锁很少发生,但一旦发生就会造成应用的停止响应。

造成死锁的代码:

"""
开发过程中使用线程,在线程间共享多个资源的时候,
如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
尽管死锁很少发生,但一旦发生就会造成应用的停止响应,程序不做任何事情。
"""
import threading
import time


lockA = threading.Lock()
lockB = threading.Lock()


def task1():
    if lockA.acquire():
        print('获取了A锁')  # 如果可以获取到锁则返回True
        time.sleep(0.5)
        if lockB.acquire():  # 如果锁被占用,等待
            print('又获取了B锁')
            lockB.release()
        lockA.release()


def task2():
    if lockB.acquire():
        print('获取了B锁')
        time.sleep(0.5)
        if lockA.acquire():
            print('又获取了A锁')
            lockA.release()
        lockB.release()


if __name__ == '__main__':
    t1 = threading.Thread(target=task1)
    t2 = threading.Thread(target=task2)

    t1.start()
    t2.start()

利用超时时间避免死锁:

import threading
import time


lockA = threading.Lock()
lockB = threading.Lock()


def task1():
    if lockA.acquire(timeout=5):
        print('获取了A锁')  # 如果可以获取到锁则返回True
        time.sleep(0.5)
        if lockB.acquire(timeout=5):  # 如果锁被占用,等待
            print('又获取了B锁')
            lockB.release()
        lockA.release()


def task2():
    if lockB.acquire(timeout=5):
        print('获取了B锁')
        time.sleep(0.5)
        if lockA.acquire(timeout=5):
            print('又获取了A锁')
            lockA.release()
        lockB.release()


if __name__ == '__main__':
    t1 = threading.Thread(target=task1)
    t2 = threading.Thread(target=task2)

    t1.start()
    t2.start()
  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章           查看所有文章
加:2021-07-29 14:47:55  更:2021-07-29 14:48:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/25 15:06:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计