详解Python中的多线程、线程锁、线程变量 – threading、Thread、Lock与ThreadLocal详解

其他关于Python的总结文章请访问:https://www.jianshu.com/nb/47435944

详解Python中的多线程、线程锁、线程变量 – threading、Thread、Lock与ThreadLocal详解

关于多进程的内容请参考:<>

一个进程可以包含多个线程,而且至少必须要有一个线程,这个线程被称为主线程,在Python中的名字为 MainThread。进程与线程最大的不同在于,进程的信息时各自的,而(同一个进程下的)线程的信息是公用的,即他们都处理、使用所在进程的信息数据等。

可以使用Python中的threading模块进行线程管理于操作。使用 threading.current_thread() 获取当前所在线程,使用线程实例的name属性获取线程的名字。

使用Thread创建多线程

一个python运行起来后对应着一个进程,这个进程的的主线程即 MainThread,使用Thread可以创建新的线程,创建时使用参数 target 绑定线程运行的目标,使用 name 参数为线程定义一个名字。

Thread的实例有的常用方法:

  • start:开始执行这个线程
  • join:等待线程执行结束

一个例子:

import time, random, threading


def print_time():
    time.sleep(random.random())
    print("I m thread {}, time now is {}".format(threading.current_thread().name, time.time()))


print("The main thread is {}".format(threading.current_thread().name))
thread1 = threading.Thread(target=print_time, name="New Thread 1")
thread2 = threading.Thread(target=print_time, name="New Thread 2")
thread3 = threading.Thread(target=print_time, name="New Thread 3")

thread1.start()
thread2.start()
thread3.start()

thread1.join()
thread2.join()
thread3.join()

得到的结果是随机的:

The main thread is MainThread
I m thread New Thread 3, time now is 1607256751.4239407
I m thread New Thread 1, time now is 1607256751.8748183
I m thread New Thread 2, time now is 1607256751.9063895

使用锁Lock修改数据

由于(同一个进程下的)多个线程使用的是同一套数据,所以如果多个线程同时访问一个数据就会造成冲突,解决的方法是使用线程锁,在某个线程修改这个数据的时候,它获得一把锁,只有获得锁的这个线程有权利修改这个数据,等修改完成后再释放锁,这样就可以保证在一个时间只有一个线程修改这个数据。如果多个线程都想请求得到锁,他们会排队获得。

Python中使用threading.Lock来完成,一个Lock实例常用的的方法有:

  • acquire:请求获得锁
  • relaese:释放锁

为例确保一个线程在使用完后必定会释放锁,一般使用try...final...语句,将释放锁的代码放在finally块里。

一个例子:一个线程要给一个数据加一,一个线程要给同一个数据减一:

import time, random, threading

number = 0
lock = threading.Lock()


def add_one():
    global number
    for i in range(20):
        lock.acquire()
        print("I m thread {}, I acquired the lock.".format(threading.current_thread().name))
        try:
            number += 1
        finally:
            lock.release()
            print("I m thread {}, I realised the lock.".format(threading.current_thread().name))


def minus_one():
    global number
    for i in range(20):
        lock.acquire()
        print("I m thread {}, I acquired the lock.".format(threading.current_thread().name))
        try:
            number -= 1
        finally:
            lock.release()
            print("I m thread {}, I realised the lock.".format(threading.current_thread().name))


thread_add = threading.Thread(target=add_one, name="Thread ADD")
thread_minus = threading.Thread(target=minus_one, name="Thread MINUS")

thread_add.start()
thread_minus.start()

thread_add.join()
thread_minus.join()

使用ThreadLocal创建进程局部变量

设想如果有多个线程,它们都要处理自己的一个变量,但是又想进行对于该变量的信息交换,这样的情况下,可以使用一个全局变量来记录每个线程的局部变量(列如一个字典),显然是很麻烦的,于是可以使用ThreadLocal来处理线程的局部变量。

一个例子:两个线程都有各自的变量number

import threading

local_variable = threading.local()


def print_number():
    number = local_variable.number
    print("I m thread {}, I m processing my number {}".format(threading.current_thread().name, number))


def set_number(num):
    local_variable.number = num
    print_number()


thread1 = threading.Thread(target=set_number, args=(1,), name="Thread 1")
thread2 = threading.Thread(target=set_number, args=(2,), name="Thread 2")

thread1.start()
thread2.start()
thread1.join()
thread2.join()

得到的结果如下:

I m thread Thread 1, I m processing my number 1
I m thread Thread 2, I m processing my number 2

© 版权声明

相关文章

暂无评论

none
暂无评论...