ThreadPoolExecutor 饥饿
ThreadPoolExcutor starvation
我正在尝试 运行 2 个不同的阻塞函数,它们使用相同的全局变量 a
。
代码:
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
import keyboard
a = 0
def incA():
global a
while True:
print(f'inc a: {a} -> {a+1}', end = '\n')
a+=1
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
def printA():
# a is read-only
while True:
print(f'print a: {a}', end = '\n')
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
with ThreadPoolExecutor(max_workers=2) as executor:
f1 = executor.submit(incA)
f2 = executor.submit(printA)
期望的输出:
.
.
.
inc a: 15640 -> 15641
print a: 15641
inc a: 15641 -> 15642
print a: 15642
inc a: 15642 -> 15643
print a: 15643
.
.
.
此代码的给定输出是这样的:
print a: 1428inc a: 1429 -> 1430
print a: 1429
inc a: 1430 -> 1431print a: 1430
inc a: 1431 -> 1432print a: 1431
inc a: 1432 -> 1433print a: 1432
inc a: 1433 -> 1434print a: 1433
inc a: 1434 -> 1435print a: 1434
inc a: 1435 -> 1436print a: 1435
inc a: 1436 -> 1437print a: 1436
这接近我想要的,但是如您所见,即使我明确地把 end='\n'
在函数中。
我尝试给系统加锁,结果导致饿死。在每个函数的 while True
循环中,我添加了这些行:
def printA():
global lock
# a is read-only
while True:
try:
lock.acquire()
print(f'print a: {a}', end = '\n')
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
finally:
lock.release()
导致此输出(饥饿):
inc a: 1319 -> 1320
inc a: 1320 -> 1321
inc a: 1321 -> 1322
inc a: 1322 -> 1323
inc a: 1323 -> 1324
inc a: 1324 -> 1325
print a: 1325
print a: 1325
print a: 1325
print a: 1325
print a: 1325
print a: 1325
使用 Ron Serruya 的回答建议 link 我们在消息中添加换行符以防止分离。
修改代码
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
import keyboard
a = 0
def incA():
global a
while True:
print(f'inc a: {a} -> {a+1}\n', end = '') # Place newline in message to prevent separation
a+=1
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
def printA():
# a is read-only
while True:
print(f'print a: {a}\n', end = '') # Place newline in message to prevent separation
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
with ThreadPoolExecutor(max_workers=2) as executor:
f1 = executor.submit(incA)
f2 = executor.submit(printA)
输出
...
inc a: 3459 -> 3460
print a: 3459
print a: 3459
inc a: 3460 -> 3461
print a: 3460
inc a: 3461 -> 3462
print a: 3461
inc a: 3462 -> 3463
inc a: 3463 -> 3464
print a: 3463
inc a: 3464 -> 3465
print a: 3464
inc a: 3465 -> 3466
print a: 3465
inc a: 3466 -> 3467
print a: 3466
...
我正在尝试 运行 2 个不同的阻塞函数,它们使用相同的全局变量 a
。
代码:
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
import keyboard
a = 0
def incA():
global a
while True:
print(f'inc a: {a} -> {a+1}', end = '\n')
a+=1
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
def printA():
# a is read-only
while True:
print(f'print a: {a}', end = '\n')
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
with ThreadPoolExecutor(max_workers=2) as executor:
f1 = executor.submit(incA)
f2 = executor.submit(printA)
期望的输出:
.
.
.
inc a: 15640 -> 15641
print a: 15641
inc a: 15641 -> 15642
print a: 15642
inc a: 15642 -> 15643
print a: 15643
.
.
.
此代码的给定输出是这样的:
print a: 1428inc a: 1429 -> 1430
print a: 1429
inc a: 1430 -> 1431print a: 1430
inc a: 1431 -> 1432print a: 1431
inc a: 1432 -> 1433print a: 1432
inc a: 1433 -> 1434print a: 1433
inc a: 1434 -> 1435print a: 1434
inc a: 1435 -> 1436print a: 1435
inc a: 1436 -> 1437print a: 1436
这接近我想要的,但是如您所见,即使我明确地把 end='\n'
在函数中。
我尝试给系统加锁,结果导致饿死。在每个函数的 while True
循环中,我添加了这些行:
def printA():
global lock
# a is read-only
while True:
try:
lock.acquire()
print(f'print a: {a}', end = '\n')
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
finally:
lock.release()
导致此输出(饥饿):
inc a: 1319 -> 1320
inc a: 1320 -> 1321
inc a: 1321 -> 1322
inc a: 1322 -> 1323
inc a: 1323 -> 1324
inc a: 1324 -> 1325
print a: 1325
print a: 1325
print a: 1325
print a: 1325
print a: 1325
print a: 1325
使用 Ron Serruya 的回答建议 link
修改代码
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
import keyboard
a = 0
def incA():
global a
while True:
print(f'inc a: {a} -> {a+1}\n', end = '') # Place newline in message to prevent separation
a+=1
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
def printA():
# a is read-only
while True:
print(f'print a: {a}\n', end = '') # Place newline in message to prevent separation
if keyboard.is_pressed('q'): # if key 'q' is pressed
break
with ThreadPoolExecutor(max_workers=2) as executor:
f1 = executor.submit(incA)
f2 = executor.submit(printA)
输出
...
inc a: 3459 -> 3460
print a: 3459
print a: 3459
inc a: 3460 -> 3461
print a: 3460
inc a: 3461 -> 3462
print a: 3461
inc a: 3462 -> 3463
inc a: 3463 -> 3464
print a: 3463
inc a: 3464 -> 3465
print a: 3464
inc a: 3465 -> 3466
print a: 3465
inc a: 3466 -> 3467
print a: 3466
...