返回顶部
首页 > 资讯 > 后端开发 > Python ># Python 多线程和锁
  • 769
分享到

# Python 多线程和锁

多线程Python 2023-01-31 08:01:13 769人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

作者博客:Http://zzir.cn/ 进程和线程 进程是执行中的计算机程序。每个进程都拥有自己的地址空间、内存、数据栈及其它的辅助数据。操作系统管理着所有的进程,并为这些进程合理分配时间。进程可以通过派生新的进程来执行其它任务,不过

作者博客:Http://zzir.cn/

进程和线程

进程是执行中的计算机程序。每个进程都拥有自己的地址空间、内存、数据栈及其它的辅助数据。操作系统管理着所有的进程,并为这些进程合理分配时间。进程可以通过派生新的进程来执行其它任务,不过每个进程都拥有自己的内存和数据栈等,进程之间的数据交换采用 进程间通信(IPC) 方式。

线程在进程之下执行,一个进程下可以运行多个线程,它们之间共享相同上下文。线程包括开始、执行顺序和结束三部分。它有一个指针,用于记录当前运行的上下文。当其它线程执行时,它可以被抢占(中断)和临时挂起(也称睡眠) ——这种做法叫做 让步(yielding)

一个进程中的各个线程与主进程共享同一片数据空间,与独立进程相比,线程之间信息共享和通信更加容易。线程一般以并发执行,正是由于这种并发和数据共享机制,使多任务间的协作成为可能。当然,这种共享也并不是没有风险的,如果多个线程访问同一数据空间,由于访问顺序不同,可能导致结果不一致,这种情况通常称为竞态条件(race condition),不过大多数线程库都有同步原语,以允许线程管理器的控制执行和访问;另一个要注意的问题是,线程无法给予公平执行时间,CPU 时间分配会倾向那些阻塞更少的函数。

全局解释器(GIL)

python 代码执行由 Python 虚拟机 (又名解释器主循环) 进行控制。Python 在设计时是这样考虑的,在主循环中同时只能有一个控制线程在执行。对 Python 虚拟机的访问由 全局解释器(GIL) 控制,这个锁用于,当有多个线程时保证同一时刻只能有一个线程在运行。

由于 Python 的 GIL 的限制,多线程更适合 I/O 密集型应用( I/O 释放了 GIL,可以允许更多的并发),对于计算密集型应用,为了实现更好的并行性,适合使用多进程,已便利用 CPU 的多核优势。Python 的多进程相关模块:subprocess、multiprocessing、concurrent.futures

threading 模块

threading 是 Python 高级别的多线程模块。

threading 模块的函数

  • active_count() 当前活动的 Thread 对象个数

  • current_thread() 返回当前 Thread 对象

  • get_ident() 返回当前线程

  • enumerater() 返回当前活动 Thread 对象列表

  • main_thread() 返回主 Thread 对象

  • settrace(func) 为所有线程设置一个 trace 函数

  • setprofile(func) 为所有线程设置一个 profile 函数

  • stack_size([size]) 返回新创建线程栈大小;或为后续创建的线程设定栈大小为 size

  • TIMEOUT_MAX Lock.acquire(), RLock.acquire(), Condition.wait() 允许的最大值

threading 可用对象列表:

  • Thread 表示执行线程的对象

  • Lock 锁原语对象

  • RLock 可重入锁对象,使单一进程再次获得已持有的锁(递归锁)

  • Condition 条件变量对象,使得一个线程等待另一个线程满足特定条件,比如改变状态或某个值

  • Semaphore 为线程间共享的有限资源提供一个"计数器",如果没有可用资源会被阻塞

  • Event 条件变量的通用版本,任意数量的线程等待某个时间的发生,在改事件发生后所有线程被激活

  • Timer 与 Thread 相识,不过它要在运行前等待一段时间

  • Barrier 创建一个"阻碍",必须达到指定数量的线程后才可以继续

Thread 类

Thread 对象的属性有:Thread.nameThread.identThread.daemon。详见(The Python Standard Library)

Thread 对象方法:
Thread.start()Thread.run()Thread.join(timeout=None)Thread.getNameThread.setNameThread.is_alive()Thread.isDaemon()Thread.setDaemon()。详见(The Python Standard Library)

使用 Thread 类,可以有很多种方法来创建线程,这里使用常见的两种:

  • 创建 Thread 实例,传给它一个函数。

  • 派生 Thread 子类,并创建子类的实例。

一个单线程栗子

#!/usr/bin/env python3

import threading
from random import randint
from time import sleep, ctime

def hi(n):
    sleep(n)
    print("ZzZzzz, sleep: ", n)    # 打印 Sleep 的秒数

def main():
    print("### Start at: ", ctime())

    for i in range(10):
        hi(randint(1,2))    # 调用十次,每次 Sleep 1秒或2秒

    print("### Done at: ", ctime())

if __name__ == '__main__':
    main()

运行结果:

### Start at:  Thu Sep  1 14:11:00 2016
ZzZzzz, sleep:  1
ZzZzzz, sleep:  2
ZzZzzz, sleep:  2
ZzZzzz, sleep:  2
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  2
### Done at:  Thu Sep  1 14:11:14 2016

一共是用了14秒。

多线程:创建 Thread 实例,传给它一个函数

直接上代码:

#!/usr/bin/env python3

import threading
from random import randint
from time import sleep, ctime

def hi(n):
    sleep(n)
    print("ZzZzzz, sleep: ", n)

def main():
    print("### Start at: ", ctime())
    threads = []

    for i in range(10):
        rands = randint(1,2)
        # 实例化每个 Thread 对象,把函数和参数传递进去,返回 Thread 实例
        t = threading.Thread(target=hi, args=(rands,))
        threads.append(t)     # 分配线程

    for i in range(10):
        threads[i].start()    # 开始执行多线程

    for i in range(10):
        threads[i].join()     # (自旋锁)等待线程结束或超时,然后再往下执行

    print("### Done at: ", ctime())

if __name__ == '__main__':
    main()

运行结果:

### Start at:  Thu Sep  1 14:18:00 2016
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
ZzZzzz, sleep:  2
ZzZzzz, sleep:  2
ZzZzzz, sleep:  2
ZzZzzz, sleep:  2
### Done at:  Thu Sep  1 14:18:02 2016

使用多线程,只用了2秒。

多线程:派生 Thread 子类,并创建子类的实例

#!/usr/bin/env python3

import threading
from random import randint
from time import sleep, ctime

class MyThread(threading.Thread):
 
    def __init__(self, func, args, times):
        super(MyThread, self).__init__()
        self.func = func
        self.args = args
        self.times = times
    
    def run(self):
        print("begin thread......", self.times)
        self.res = self.func(*self.args)
        print("end threads......", self.times)


def hi(n):
    sleep(n)
    print("ZzZzzz, sleep: ", n)

def main():
    print("### Start at: ", ctime())
    threads = []

    for i in range(10):
        rands = randint(1,2)
        t = MyThread(hi, (rands,), i+1)
        threads.append(t)

    for i in range(10):
        threads[i].start()

    for i in range(10):
        threads[i].join()

    print("### Done at: ", ctime())

if __name__ == '__main__':
    main()

执行结果:

### Start at:  Thu Sep  1 14:47:09 2016
begin thread...... 1
begin thread...... 2
begin thread...... 3
begin thread...... 4
begin thread...... 5
begin thread...... 6
begin thread...... 7
begin thread...... 8
begin thread...... 9
begin thread...... 10
ZzZzzz, sleep:  1
ZzZzzz, sleep:  1
end threads...... 1
end threads...... 4
ZzZzzz, sleep:  1
end threads...... 7
ZzZzzz, sleep:  1
end threads...... 3
ZzZzzz, sleep:  1
end threads...... 9
ZzZzzz, sleep:  2
end threads...... 2
ZzZzzz, sleep:  2
end threads...... 5
ZzZzzz, sleep:  2
ZzZzzz, sleep:  2
end threads...... 10
end threads...... 6
ZzZzzz, sleep:  2
end threads...... 8
### Done at:  Thu Sep  1 14:47:11 2016

这个栗子对 Thread 子类化,而不是对其实例化,使得定制线程对象更具灵活性,同时也简化线程创建的调用过程。

线程锁

当多线程争夺锁时,允许第一个获得锁的线程进入临街区,并执行代码。所有之后到达的线程将被阻塞,直到第一个线程执行结束,退出临街区,并释放锁。需要注意,那些阻塞的线程是没有顺序的。

举个栗子:

#!/usr/bin/env python3

import threading
from random import randint
from time import sleep, ctime

L = threading.Lock() # 引入锁

def hi(n):
    L.acquire()    # 加锁
    for i in [1,2]:
        print(i)
        sleep(n)
        print("ZzZzzz, sleep: ", n)
    L.release()    # 释放锁

def main():
    print("### Start at: ", ctime())
    threads = []

    for i in range(10):
        rands = randint(1,2)
        t = threading.Thread(target=hi, args=(rands,))
        threads.append(t)

    for i in range(10):
        threads[i].start()

    for i in range(10):
        threads[i].join()

    print("### Done at: ", ctime())

if __name__ == '__main__':
    main()

运行上面的代码,再将锁的代码注释掉,对比下输出。

--结束END--

本文标题: # Python 多线程和锁

本文链接: https://lsjlt.com/news/193279.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • # Python 多线程和锁
    作者博客:http://zzir.cn/ 进程和线程 进程是执行中的计算机程序。每个进程都拥有自己的地址空间、内存、数据栈及其它的辅助数据。操作系统管理着所有的进程,并为这些进程合理分配时间。进程可以通过派生新的进程来执行其它任务,不过...
    99+
    2023-01-31
    多线程 Python
  • Python多线程编程,线程锁
    多线程threading 模块创建线程创建自己的线程类线程通信线程同步互斥方法线程锁@需要了解!!!   什么是线程? 线程也是一种多任务的编程方法,可以利用计算机多核资源完成程序的并发运行。 线程又被称为轻量级进程 ...
    99+
    2023-01-30
    线程 多线程 Python
  • python多线程互斥锁与死锁
    目录一、多线程间的资源竞争二、互斥锁1.互斥锁示例2.可重入锁与不可重入锁三、死锁一、多线程间的资源竞争 以下列task1(),task2()两个函数为例,分别将对全局变量num加一...
    99+
    2024-04-02
  • C#多线程系列之多线程锁lock和Monitor
    目录1,Locklock 原型lock 编写实例2,Monitor怎么用呢解释一下示例设置获取锁的时效1,Lock lock 用于读一个引用类型进行加锁,同一时刻内只有一个线程能够访...
    99+
    2024-04-02
  • python多线程线程锁的使用方法
    小编给大家分享一下python多线程线程锁的使用方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!python的数据类型有哪些python的数据类型:1. 数字类...
    99+
    2023-06-14
  • 如何使用多线程和锁
    本篇内容介绍了“如何使用多线程和锁”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、前言你只面向工作学习吗...
    99+
    2024-04-02
  • C#多线程之线程锁
    目录一、Mutex类二、Mutex的用途三、Semaphore信号量1、简介2、初始化3、WaitOne()和Release()四、Monitor类典型的生产者与消费者实例五、Loc...
    99+
    2024-04-02
  • Python线程和锁是什么
    本篇内容主要讲解“Python线程和锁是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python线程和锁是什么”吧!概述线程和锁是硬件底层的软件定义形式化,因此包含最简单的可能并发模型。它...
    99+
    2023-06-16
  • Python线程锁
    多线程的优势:可以同时运行多个任务但是当多个线程同时访问共享数据时,可能导致数据不同步,甚至错误!so,不使用线程锁, 可能导致错误购买车票--线程锁[root@~]# cat test.py #-*- coding:utf-8 -*- i...
    99+
    2023-01-31
    线程 Python
  • Java多线程怎么显示锁和内置锁
    这篇文章主要介绍Java多线程怎么显示锁和内置锁,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Java中具有通过Synchronized实现的内置锁,和ReentrantLock实现的显示锁,这两种锁各有各的好处,算...
    99+
    2023-05-30
    java
  • 异步 Python 编程:解锁多线程和并发的奥秘
    在现代软件开发中,异步编程已成为提高应用程序性能和响应能力的关键。Python 作为一种多功能语言,通过其并行和异步编程特性提供了强大的异步解决方案。本文将深入探讨异步 Python 编程,揭开多线程和并发的奥秘。 多线程的理解 多线程是...
    99+
    2024-03-09
    引言
  • python多线程和多进程(二)
    ---恢复内容开始--- 一、多进程   1、multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。 import time from mult...
    99+
    2023-01-30
    多线程 进程 python
  • python socket多线程和多进程
    在socket中,如果直接创建的话,是只能接受一个用户的请求需要实现socketserver中的handle方法,可以实现多进程并发访问 SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理...
    99+
    2023-01-31
    多线程 进程 python
  • python多线程互斥锁与死锁问题详解
    目录一、多线程共享全局变量二、给线程加一把锁锁三、死锁问题总结一、多线程共享全局变量 代码实现的功能: 创建work01与worker02函数,对全局变量进行加一操作创建main函数...
    99+
    2024-04-02
  • Java多线程之多种锁和阻塞队列
    目录一、悲观锁和乐观锁1.1. 乐观锁1.2. 悲观锁二、公平锁和非公平锁三、可重入锁(递归锁)四、自旋锁五、独占锁(写)/共享锁(读)六、什么是阻塞队列?七、阻塞队列(Blocki...
    99+
    2024-04-02
  • Java多线程(3)---锁策略、CAS和JUC
    目录 前言 一.锁策略 1.1乐观锁和悲观锁 ⭐ 两者的概念 ⭐实现方法 1.2读写锁  ⭐概念 ⭐实现方法 1.3重量级锁和轻量级锁 1.4自旋锁和挂起等待锁 ⭐概念 ⭐代码实现 1.5公平锁和非公平锁 1.6可重入锁和不可重入锁 二.C...
    99+
    2023-08-31
    开发语言 多线程 java-ee
  • C#多线程锁lock和Monitor怎么用
    本文小编为大家详细介绍“C#多线程锁lock和Monitor怎么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#多线程锁lock和Monitor怎么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1,Loc...
    99+
    2023-06-29
  • python多进程和多线程介绍
    目录一、什么是进程和线程 二、多进程和多线程 三、python中的多进程和多线程1、多进程2、多线程一、什么是进程和线程  进程是分配资源的最小单位,线...
    99+
    2024-04-02
  • python线程锁和全局锁有什么作用
    Python线程锁和全局锁都是用来控制多线程并发访问共享资源的工具,可以确保线程安全地访问共享资源。 线程锁是在代码块中使用的锁,它...
    99+
    2024-03-15
    python
  • python多线程死锁现象怎么解决
    今天小编给大家分享一下python多线程死锁现象怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一 死锁现象所谓死锁:...
    99+
    2023-07-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作