Home > Back-end >  python threading local unexpected value
python threading local unexpected value

Time:11-12

Why is getattr not working? I am not trying to set a default value to threadLocal, I want to know why getattr does not work the way I want it to? tried to lock, same output

Expected Output

0
1
2
3
4
main thread

Current Output

0
0
0
0
0
main thread

Code

from concurrent.futures import ThreadPoolExecutor
from threading import local

threadLocal = local()
threadLocal.x = 'main thread'

def f(x):
    # threadLocal.x = x # this works
    threadLocal.x = getattr(threadLocal, 'x', x) # this does not work
    return threadLocal.x

pool = ThreadPoolExecutor(5)
result = pool.map(f, range(0, 5))
for i in result:
    print(i)

print(threadLocal.x)

CodePudding user response:

A Thread pool shares its worker threads between work items. That means that if a work item is finished before the next, both can run on the same thread and thus see the same thread locals.

This is exactly what happens here: since f is very quick to execute, most or all work items run in the first worker thread. The first task f(0) sets threadLocal.x = 0 here, and other tasks running in the same thread thus read threadLocal.x = 0.

You can circumvent this by (artificially) increasing the runtime of f.

def f(x):
    time.sleep(0.2)  # delay for other work items to start running
    threadLocal.x = getattr(threadLocal, 'x', x) # this works now
    return threadLocal.x

Note that any additional operation may be sufficient to break the timing issue: that includes printing the argument and thread local, for example.

  • Related