gpt4 book ai didi

Python 线程 - 关键部分

转载 作者:太空狗 更新时间:2023-10-29 17:37:59 25 4
gpt4 key购买 nike

什么是线程的“临界区”(在 Python 中)?

A thread enters the critical section by calling the acquire() method, which can either be blocking or non-blocking. A thread exits the critical section, by calling the release() method.

- Understanding Threading in Python, Linux Gazette

另外,锁的目的是什么?

最佳答案

其他人给出了很好的定义。这是经典示例:

import threading
account_balance = 0 # The "resource" that zenazn mentions.
account_balance_lock = threading.Lock()

def change_account_balance(delta):
global account_balance
with account_balance_lock:
# Critical section is within this block.
account_balance += delta

假设 += 运算符由三个子组件组成:

  • 读取当前值
  • 将 RHS 添加到该值
  • 将累加值写回 LHS(用 Python 术语从技术上绑定(bind))

如果您没有 with account_balance_lock 语句并且并行执行两个 change_account_balance 调用,您最终可能会以危险的方式交错三个子组件操作。假设您同时调用 change_account_balance(100)(又名 pos)和 change_account_balance(-100)(又名 neg)。这可能会发生:

pos = threading.Thread(target=change_account_balance, args=[100])
neg = threading.Thread(target=change_account_balance, args=[-100])
pos.start(), neg.start()
  • pos: 读取当前值-> 0
  • neg: 读取当前值 -> 0
  • pos: 将当前值添加到读取值-> 100
  • neg: 将当前值添加到读取值 -> -100
  • pos: 写入当前值-> account_balance = 100
  • neg: 写入当前值 -> account_balance = -100

因为您没有强制操作在离散的 block 中发生,所以您可以有三种可能的结果(-100、0、100)。

with [lock] 语句是一个单一的、不可分割的操作,它说,“让我成为执行此代码块的唯一线程。如果有其他东西正在执行,那就太棒了——我”我等一下。”这确保了对 account_balance 的更新是“线程安全的”(并行安全的)。

注意:此架构有一个警告:您必须记住每次需要时都获取account_balance_lock(通过with)操作 account_balance 以使代码保持线程安全。有一些方法可以让它不那么脆弱,但这是对另一个问题的答案。

编辑:回想起来,可能很重要的一点是 with 语句隐式调用锁上的阻塞 acquire —— 这是上述线程对话框的“我会等待”部分。相比之下,非阻塞获取会说,“如果我不能立即获取锁,请告诉我”,然后依靠你来检查你是否获得了锁。

import logging # This module is thread safe.
import threading

LOCK = threading.Lock()

def run():
if LOCK.acquire(False): # Non-blocking -- return whether we got it
logging.info('Got the lock!')
LOCK.release()
else:
logging.info("Couldn't get the lock. Maybe next time")

logging.basicConfig(level=logging.INFO)
threads = [threading.Thread(target=run) for i in range(100)]
for thread in threads:
thread.start()

我还想补充一点,锁的主要目的是保证获取的原子性(acquire 跨线程的不可分割性),简单的 bool 标志无法保证这一点。原子操作的语义大概也是另外一个问题的内容。

关于Python 线程 - 关键部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/419145/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com