Python 多线程编程

Thread类

class Thread:
    def __init__(self,group=None,target=None,name=None,args=(),kwargs=None,*,daemon=None)
  • group:None,为日后扩展 ThreadGroup 类实现而保留。

  • target:run() 方法调用的目标函数。

  • name:线程名。默认值为Thread-N

  • args:传递给目标函数的位置参数元组。

  • kwargs:传递给目标函数的关键字参数字典。

  • daemon:守护线程。

Thread类的常用方法和属性

start():启动线程,在一个线程里最多只能被调用一次。

run():调用 target 传递的目标函数,并从 args 和 kwargs 分别获取的位置和关键字参数。

name:线程名。

getName():获取线程名。

setName():设置线程名。

ident:线程标识符,是个非零整数。如果线程尚未启动则为None。

daemon:是否是守护线程的布尔值,默认为False。

isDaemon():返回线程是否是守护线程。

setDaemon():设置线程为守护线程。

join([time]):阻塞调用该方法的线程,直到被调用该方法的线程结束或超时。

is_alive():返回线程是否存活。

threading模块常用方法和属性

active_count():返回当前存活的 Thread 对象的计数。

enumerate():以列表形式返回当前存活的 Thread 对象。

current_thread():返回当前对应调用者的控制线程的 Thread 对象。

main_thread():返回主 Thread 对象。

get_ident():返回当前线程的"线程标识符"。

创建线程

  • 可调用对象传递给构造函数

  • 重写子类的 run() 方法

1. 可调用对象传递给构造函数

import threading
import time

def func(n):
    print("task", n)
    time.sleep(2)

for i in range(2):
    t = threading.Thread(target=func, args=(i,)) # 创建线程
    t.start() # 启动线程

2. 重写子类的 run() 方法

import threading
import time

class MyThread(threading.Thread):
    def __init__(self, n):
        super().__init__()
        self.n = n

    def run(self):
        print("task", self.n)
        time.sleep(2)

for i in range(2):
    t = MyThread(i)
    t.start()  

全局解释器锁

  全局解释器锁(Global Interpreter Lock,简称GIL),是计算机程序设计语言解释器用于同步线程的工具,使得在同一进程内任何时刻仅有一个线程在执行。即使在多核CPU平台上,同一时刻也只有一个获得GIL的线程在执行,其他线程处于阻塞状态。

  • CPython使用操作系统的原生线程,由操作系统负责调度。

  • 每个解释器进程有唯一的主线程和用户定义的任意数量子线程。

  • 每个解释器进程有且仅有一个GIL,当解释器启动时,主线程获取GIL。

  • 线程执行前要先获取GIL,当遇到I/O操作时释放GIL。

线程锁

  原始锁处于"锁定"或者"非锁定"状态,被创建时是非锁定状态。它有两个基本方法:acquire(),release()。

  • 当状态是非锁定时,线程调用 acquire() 获取锁,并阻塞其他线程,直到锁被释放,将状态修改为锁定。

  • 当状态是锁定时,任何线程都可以调用 release() 释放锁,将状态修改为非锁定。

import threading
import time

lock = threading.Lock()

def func(n):
    lock.acquire()    # 获取锁
    print("task", n)
    lock.release()    # 释放锁
    time.sleep(2)

for i in range(2):
    t = threading.Thread(target=func, args=(i,))
    t.start()

信号量

  信号量管理一个内部计数器,调用 acquire() 方法时计数器-1,调用 release() 方法时计数器+1。当计数器为0时将会阻塞,直到线程调用 release() 方法。

import threading
import time

semaphore = threading.BoundedSemaphore(2)

def func(n, se):
    se.acquire()
    print("task", n)
    time.sleep(2)
    se.release()

for i in range(2):
    t = threading.Thread(target=func, args=(i,semaphore))
    t.start()

事件

  事件是线程之间的一种通信机制:一个线程发出事件信号,其他线程等待该信号。

  事件对象管理一个内部标志Flag,初始为false。调用 set() 方法可将其设置为 true,调用 clear() 方法可将其设置为false,调用 wait() 方法将阻塞线程直到标志为 true。

import threading
import time

event = threading.Event()

def func():
    print(threading.current_thread().getName(), "ready")
    time.sleep(3)
    event.wait()
    print(threading.currentThread().getName(), "go")

for i in range(2):
    t = threading.Thread(target=func)
    t.start()

print("Ready?Go!")
event.set()
posted @ 2019-05-19 10:30  PIPO2  阅读(279)  评论(0编辑  收藏  举报