Can python threads access variables in the namespace?

后端 未结 3 992
没有蜡笔的小新
没有蜡笔的小新 2021-01-31 05:36

I have a script that creates a bunch of threads, runs a program to use the threads to run tasks from a queue, and returns something from each thread. I want to count how many of

相关标签:
3条回答
  • 2021-01-31 06:01

    Based on Python variable scope error,

    I should have put "global successful" under "def foo():".

    Oops.

    0 讨论(0)
  • 2021-01-31 06:08

    The problem happens because a variable that is assigned inside a function is considered to be local to that function. If you want to modify the value of a variable successfull, that is created outside a foo, you need to explicitly inform the interpreter that you are going to work with a global variable inside a function. This can be done in the following way:

    def foo():
        global successfull
        while True:
            task=q.get()
            #do some work
            print task
            successful+=1 # triggers an error
            q.task_done()
    

    Now the code should work as expected.

    0 讨论(0)
  • 2021-01-31 06:14
    successful+=1
    

    is not a thread-safe operation. With multiple threads trying to increment a shared global variable, collisions may happen and successful will not be incremented properly.

    To avoid this error, use a lock:

    lock = threading.Lock()
    def foo():
        global successful
        while True:
            ...
            with lock:
                successful+=1 
    

    Here is some code to demonstrate that x += 1 is not threadsafe:

    import threading
    lock = threading.Lock()
    x = 0
    def foo():
       global x
       for i in xrange(1000000):
           # with lock:    # Uncomment this to get the right answer
                x += 1
    threads = [threading.Thread(target=foo), threading.Thread(target=foo)]
    for t in threads:
        t.daemon = True    
        t.start()
    for t in threads:
        t.join()
    
    print(x)
    

    yields:

    % test.py 
    1539065
    % test.py 
    1436487
    

    These results do not agree and are less than the expected 2000000. Uncommenting the lock yields the correct result.

    0 讨论(0)
提交回复
热议问题