Python多线程

1.多线程基础知识

使用Python的Threading库可以实现多线程,先来介绍基本的代码:

# 建立线程,将target指定为要执行的function,name就是设定的线程名称,若要传入参数,可以设定args,设定格式一定要是Tuple(变量名1,变量名2,...)
threading.Thread(target=function, name="Thread名字", args=tuple(,))
# 开始执行指定的线程,start前面要放指定的线程名称
<Thread>.start()
# 将主线程暂停,等待指定的线程结束,join前面要放指定的线程名
<Thread>.join()
# 查看目前有多少个线程
threading.active_count()
# 查看目前使用线程的信息
threading.enumerate()
# 查看目前在哪个线程中
threading.current_thread()

接下来示范一些简单的执行线程的操作

  • 建立线程
    使用threading.Thread(target=thread_job)建立一个线程,并用start开始执行
import threading
def thread_job():
	print("abc")
added_thread = threading.Thread(target=thread_job)
added_thread.start()
# =========output========
# abc
  • 等待指定线程结束
    使用join()将主线程暂停,等待指定的线程结束,主线程才会结束。以下范例为未加及加了join的代码与结果比较
# 未加join
import threading
import time
def thread_first_job(x):
	time.sleep(0.1)
	print("This is the first thread", x)

def thread_second_job(x):
	print("This is the second thread", x)

# 若thread要传入参数格式指定为(x,)
first_thread = threading.Thread(target=thread_first_job, args=("Hi",))

second_thread = threading.Thread(target=thread_second_job, args=("Hello",))

first_thread.start()
second_thread.start()
print("all done")
# --------output--------
# This is the second thread Hello
# all done
# This is the first thread Hi


# 加入join()
import threading
import time
def thread_first_job(x):
	time.sleep(0.1)
	print("This is the first thread", x)

def thread_second_job(x):
	print("This is the second thread", x)

# 若thread要传入参数格式指定为(x,)
first_thread = threading.Thread(target=thread_first_job, args=("Hi",))

second_thread = threading.Thread(target=thread_second_job, args=("Hello",))

first_thread.start()
second_thread.start()

# 使用join等待first_thread执行完毕
first_thread.join()
print("all done")
# --------output--------
# This is the second thread Hello
# This is the first thread Hi
# all done

未加join()的输出并不会等待first thread输出再进行从下一步,而加了join()后则会等待输出first thread

  • setDaemon(bool)
    若希望再主线程执行完毕后,不管其他的Thread是否已经执行完毕,都强制跟主线程一起结束,必须写在start()之前,默认值为False。
import threading
import time 
def thread_first_job(x):
    time.sleep(5)
    print("This is the first thread ", x)
 
def thread_second_job(x):
    print("This is the second thread ", x)
 
first_thread = threading.Thread(target = thread_first_job, args=("Hi",))
second_thread = threading.Thread(target = thread_second_job, args=("Hello",))
second_thread.setDaemon(True)
first_thread.start()
second_thread.start()

2.多线程的同步机制(Synchronized)

同步机制(Synchronized)有以下几种:互斥量(Mutex),讯号量(Semaphore),条件变量(Condition Variable),原子变量(Atomic),队列(Queue),事件(Event)

  • Queue()
    Thread无法回传值,所以要使用Queue.put()将要传回的值存入Queue,再用Queue.get()取出
import threading
from queue import Queue

# 将要回传的值存入Queue
def thread_job(data, q):
	for i in range(len(data)):
		data[i] = data[i]*2
	q.put(data)

def multithread():
	data = [[1, 2, 3], [4, 5, 6]]
	q = Queue()
	all_thread = []
	# 使用multi-thread
	for i in range(len(data)):
		thread = threading.Thread(target=thread_job, args=(data[i], q))
		thread.start()
		all_thread.append(thread)
	
	# 等待全部Thread执行完毕
	for t in all_thread:
		t,join()
	# 使用q.get()取出要传回的值
	result = []
	for _ in range(len(all_thread)):
		result.append(q.get())
	print(result)
multithread()
# ------output------
# [[2, 4, 6], [8, 10, 12]]
  • Lock()
    当同时有几个Thread要用到同一个数据时候,为了不发生Race Condition的现象,需要使用lock.acquire()以及lock.release()来将其锁定住,不让其他Thread执行。
import threading

def thread_first_job():
	global a, lock
	lock.acquire()
	
	for _ in range(3):
		a += 1
		print("This is the first thread", a)
	lock.release()

def thread_second_job():
	global a, lock
	lock.acquire()
	
	for _ in range(3):
		a -= 1
		print("This is the second thread", a)
	lock.release()

a = 0
lock = threading.Lock()
first_thread = threading.Thread(target=thread_first_job)
second_thread = threading.Thread(target=thread_second_job)

first_thread.start()
second_thread.start()

first_thread.join()
second_thread.join()
#----------output----------
# 会先由first_thread执行,执行完后才会交给second_thread
# This is the first thread 1
# This is the first thread 2
# This is the first thread 3
# This is the second thread 2
# This is the second thread 1
# This is the second thread 0
  • Semaphore
    Semaphore跟Lock类似,但是Semaphore多了计数器的功能,可以允许多个线程同时执行
import threading

def thread_first_job():
	global a
	# 取得旗标
	semaphore.acquire()
	for _ in range(3):
		a += 1
		print("This is the first thread", a)
	semaphore.release()

def thread_second_job():
	global a
	# 取得旗标
	semaphore.acquire()
	for _ in range(3):
		a -= 1
		print("This is the second thread", a)
	semaphore.release()

a = 0
# 设定旗标计数器为2
semaphore = threading.Semaphore(2)
first_thread = threading.Thread(target=thread_first_job)
second_thread = threading.Thread(target=thread_second_job)

first_thread.start()
second_thread.start()

first_thread.join()
second_thread.join()
#----------output----------
# first_thread与second_thread会同时进行
# This is the first thread 1
# This is the second thread 0
# This is the second thread -1
# This is the second thread -2
# This is the first thread -1
# This is the first thread 0
  • RLock
    RLock跟Lock类似,但RLock可允许同一个线程重复取得锁定的使用权,使用acquire取得rlock,release释放rlock
import threading
rlock = threading.RLock()
rlock.acquire()
rlock.acquire()
rlock.release()
rlock.release()
  • Condition
    提供比Lock,RLock更高级的功能;等待wait(),唤醒等待中的线程notify(),唤醒所有等待中的线程notifyAll(),也提供了acquire,release方法,threading.Condition在内部维护一个锁对象(默认是RLock),可以在创建Condition对象的时候把锁对象作为参数传入
import threading
def thread_first_job():
    global a, cond
 
    # 取得 lock
    cond.acquire()
    print("Acquire the condition lock")
    # 线程进入等待状态
    if a == 0:
        print("Wait…")
        cond.wait()
    # 唤醒线程
    print("Notify to wake up…")
    cond.notify()
 
    for _ in range(3):
         a += 1
         print("This is the first thread ", a)
 
    # 释放lock
    cond.release()
 
def thread_second_job():
    global a, cond
 
    # 取得 lock
    cond.acquire()
 
    # 唤醒线程
    cond.notify()
    a += 1
 
    # 释放 lock
    cond.release()
a = 0
cond = threading.Condition()
first_thread = threading.Thread(target = thread_first_job)
second_thread = threading.Thread(target = thread_second_job)
first_thread.start()
second_thread.start()
first_thread.join()
second_thread.join()
# ====== output ======
# Acquire the condition lock
# Wait...
# Notify to wake up...
# This is the first thread  2
# This is the first thread  3
# This is the first thread  4
  • Event
    用于线程间的通信,发送线程设置的信号,若信号为True,其他等待的线程接收到信号后会被唤醒。提供设置信号event.set(),等待信号event.wait(),清除信号event.clear()功能
import threading
import time
def thread_first_job():
    global a
 
    # 线程等待状态
    print("Wait…")
    event.wait()
 
    for _ in range(3):
        a += 1
        print("This is the first thread ", a)
a = 0
# 创建 event
event = threading.Event()
first_thread = threading.Thread(target = thread_first_job)
first_thread.start()
time.sleep(3)
# 唤醒等待状态的线程
print("Wake up the thread…")
event.set()
first_thread.join()
# ====== output ======
# Wait...
# Wake up the thread...
# This is the first thread  1
# This is the first thread  2
# This is the first thread  3

参考目录

https://medium.com/ching-i/%E5%A4%9A%E5%9F%B7%E8%A1%8C%E7%B7%92-python-threading-52e1dfb3d5c9

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值