721 字
4 分钟
多并发编程-多线程

多并发编程-多线程#

守护线程/守护进程 - daemon#

如果主线程结束了守护线程也不再保留即使守护线程还在执行(没有结束)

import threading
import time
def show_message(content):
while True:
print(content, end='')
def main():
threading.Thread(
target=show_message, args=('Ping', ), daemon=True
).start()
threading.Thread(
target=show_message, args=('Pong', ), daemon=True
).start()
sleep(5)

上面这段直接跑会报 NameError: name 'sleep' is not defined——sleep 来自 time 模块,要么 import time 后写 time.sleep(5),要么 from time import sleep

Lock - 多个线程竞争临界资源(资源只有1个) - 获得锁才能操作资源

Condition — 基于Lock对象可以创建它 - wait() / notify_all()

实现线程调度

Semaphore - 多个线程竞争资源(资源有多个,但线程数量大于资源数量)

  • 多个线程通信比较简单因为可以共享内存

  • 多个进程通信相对比较困难,可以使用multiprocessing.Queue,通过多个进程共享一个队列来实现进程间的通信

生产者消费者模型 / 哲学家进餐模型 - 多线程编程模型

三种方式实现多线程#

多线程程序如果没有竞争资源的场景那么通常会比较简单

临界资源 - 被多个线程竞争的资源

当多个线程竞争临界资源的时候如果缺乏必要的保护措施就会导致数据错乱

1. 定义线程类#
import threading
import time
class Account(object):
"""银行账户"""
def __init__(self):
self.balance = 0.0
self.lock = threading.Lock()
def deposit(self, money):
# 通过锁保护临界资源
# 可以写try-finally也可以使用上下文语法
# self.lock.acquire()
# try:
# pass
# finally:
# self.lock.release()
with self.lock:
new_balance = self.balance + money
time.sleep(0.001)
self.balance = new_balance
class AddMoneyThread(threading.Thread):
def __init__(self, account, money):
self.account = account
self.money = money
# 自定义线程的初始化方法中必须调用父类的初始化方法
super().__init__()
# run方法是线程启动之后要执行的回调方法(钩子函数)
# 所以启动线程不能够直接调用run方法而是通过start方法启动线程
# 什么时候需要使用回调式编程?
# 你知道要做什么但不知道什么时候会做这件事情
def run(self):
# 线程启动之后要执行的操作
self.account.deposit(self.money)
def main():
a1 = Account()
threads = []
for _ in range(100):
t = AddMoneyThread(a1, 1)
threads.append(t)
t.start()
for t in threads:
# 等待线程执行完
t.join()
print(a1.balance)
if __name__ == '__main__':
main()
2. 直接通过threading.Thread#
def add_money(account, money):
account.deposit(money)
threads = []
account = Account()
for _ in range(100):
t = threading.Thread(target=add_money, args=(account, 1))
threads.append(t)
t.start()
for t in threads:
t.join()
print(account.balance)
3.调用线程池中的线程执行特定任务#
from concurrent.futures import ThreadPoolExecutor
# 创建线程池
pool = ThreadPoolExecutor(max_workers=10)
futures = []
# 调用线程池中的线程来执行特定的任务
for _ in range(100):
future = pool.submit(add_money, account, 1)
futures.append(future)
pool.shutdown()
for future in futures:
future.result()
print(account.balance)
# 也可以用上下文方法
futures = []
with ThreadPoolExecutor(max_workers=10) as pool:
for _ in range(100):
futures.append(pool.submit(add_money, account, 1))
for future in futures:
# 获取函数add_money的返回值
future.result()
多并发编程-多线程
https://gilgameshzzz.github.io/posts/多并发编程-多线程/
作者
Amadeus
发布于
2019-02-28
许可协议
CC BY-NC-SA 4.0