cgiustini
cgiustini

Reputation: 33

Python: sharing a list between threads

I'm trying to understand the nuances of how threads interact the variable space they share when running in the same process. The following code shows two functions, prod and consum, that are spun off in different threads. The two functions are given the same list and lock argument: they use da_list to share data and they use the lockguy to synchronize/thread-safe the sharing.

My main question is: when I run this code, it prints out (1, 0, 0, 0, 0 ...) instead of the (1,2,3,4,5,6 ...) I'm expecting. When I remove the l =[0] line in the consum function, I get the expected behavior. Why does the l = [0] screw it up? When consum finishes, da_list should be [0]. A subsequent call of prod should reset da_list to [da_int]. Thanks for the help.

import threading
import time

    def prod(l,lock):
        da_int = 0
        while True:
            with lock:
                time.sleep(0.1)
                da_int += 1
                l[0] = da_int

    def consum(l,lock):

        data = ''

        while True:
            with lock:
                time.sleep(0.1)
                print(l[0])
                l = [0]

    def main():

        da_list = [0]
        lockguy = threading.Lock()


        thread1 = threading.Thread(target = prod, args=(da_list,lockguy))
        thread2 = threading.Thread(target = consum, args=(da_list,lockguy))
        thread1.daemon = True
        thread2.daemon = True
        thread1.start()
        thread2.start()

        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            pass
        finally:
            print('done')




    if __name__ == '__main__':
        main()

Upvotes: 3

Views: 10203

Answers (1)

Robᵩ
Robᵩ

Reputation: 168596

l = [0]

You seem to be confused about how assignment works in Python. You seem to think that the above line modifies the object to which l was previously bound. It does not.

The above line creates a new list and binds the local name l to it. Whatever object l may have been bound to previously is no longer related to the name l. Any subsequent use of l in this scope will refer to this newly created list.

Consider this single-threaded code:

a = b = [1]  # a and b are both bound to the same list
print a,b    # [1] [1]
b[0] = 2     # modifies the object to which a and b are bound
print a,b    # [2] [2]
b = [0]      # now b is bound to a new list
print a,b    # [2] [0]

Notice how b[0] = 2 and b = [0] differ. In the first one, the object to which b is bound is modified. In the second, b is bound to a whole new object.

Similarly, l = [0] in your code binds l to a new object and you have lost and cannot regain any reference you had to the original object.

Upvotes: 5

Related Questions