并发编程处理

pull/1039/head
breayhing 2024-07-11 22:55:35 +08:00
parent 180cf99704
commit 75dd526d5c
3 changed files with 131 additions and 0 deletions

View File

@ -374,6 +374,63 @@ if __name__ == '__main__':
> **思考**将上面的代码修改为5个线程向银行账户存钱5个线程从银行账户取钱取钱的线程在银行账户余额不足时需要停下来等待存钱的线程将钱存入后再尝试取钱。这里需要用到线程调度的知识大家可以自行研究下`threading`模块中的`Condition`类,看看是否能够完成这个任务。
解答:
```python
import time
from concurrent.futures import ThreadPoolExecutor
from threading import Condition
class Account(object):
"""银行账户"""
def __init__(self):
self.balance = 0.0
# 初始化一个Condition对象用于线程间协调
self.condition = Condition()
def deposit(self, money):
# 存钱操作
with self.condition:
# 更新余额
new_balance = self.balance + money
time.sleep(0.01) # 模拟延迟
self.balance = new_balance
# 通知所有等待的线程,存钱操作完成
self.condition.notify_all()
print(f'Deposited {money}, new balance is {self.balance}')
def withdraw(self, money):
# 取钱操作
with self.condition:
# 如果余额不足,等待
while self.balance < money:
self.condition.wait() # 等待通知
# 更新余额
new_balance = self.balance - money
time.sleep(0.01) # 模拟延迟
self.balance = new_balance
print(f'Withdrew {money}, new balance is {self.balance}')
def main():
"""主函数"""
account = Account()
# 使用ThreadPoolExecutor创建一个线程池
with ThreadPoolExecutor(max_workers=10) as pool:
# 提交5个存钱任务和5个取钱任务
for _ in range(5):
pool.submit(account.deposit, 1)
pool.submit(account.withdraw, 1)
# 等待所有线程完成
time.sleep(2)
print(f'Final balance: {account.balance}')
if __name__ == '__main__':
main()
```
### GIL问题
如果使用官方的 Python 解释器(通常称之为 CPython运行 Python 程序,我们并不能通过使用多线程的方式将 CPU 的利用率提升到逼近400%对于4核 CPU或逼近800%对于8核 CPU这样的水平因为 CPython 在执行代码时,会受到 GIL全局解释器锁的限制。具体的说CPython 在执行任何代码时,都需要对应的线程先获得 GIL然后每执行100条字节码指令CPython 就会让获得 GIL 的线程主动释放 GIL这样别的线程才有机会执行。因为 GIL 的存在,无论你的 CPU 有多少个核,我们编写的 Python 代码也没有机会真正并行的执行。

View File

@ -0,0 +1,42 @@
import time
from concurrent.futures import ThreadPoolExecutor
from threading import Condition, Thread
class Account(object):
"""银行账户"""
def __init__(self):
self.balance = 0.0
self.condition = Condition()
def deposit(self, money):
with self.condition:
new_balance = self.balance + money
time.sleep(0.01)
self.balance = new_balance
self.condition.notify_all() # 通知所有等待的线程
print(f'Deposited {money}, new balance is {self.balance}')
def withdraw(self, money):
with self.condition:
while self.balance < money:
self.condition.wait() # 等待通知
new_balance = self.balance - money
time.sleep(0.01)
self.balance = new_balance
print(f'Withdrew {money}, new balance is {self.balance}')
def main():
"""主函数"""
account = Account()
with ThreadPoolExecutor(max_workers=10) as pool:
for _ in range(5):
pool.submit(account.deposit, 1)
pool.submit(account.withdraw, 1)
time.sleep(2) # 等待所有线程完成
print(f'Final balance: {account.balance}')
if __name__ == '__main__':
main()

32
Day61-65/formal.py 100644
View File

@ -0,0 +1,32 @@
import time
from concurrent.futures import ThreadPoolExecutor
from threading import RLock
class Account(object):
"""银行账户"""
def __init__(self):
self.balance = 0.0
self.lock = RLock()
def deposit(self, money):
# 通过上下文语法获得锁和释放锁
with self.lock:
new_balance = self.balance + money
time.sleep(0.01)
self.balance = new_balance
def main():
"""主函数"""
account = Account()
with ThreadPoolExecutor(max_workers=16) as pool:
for _ in range(100):
pool.submit(account.deposit, 1)
print(account.balance)
if __name__ == '__main__':
main()