Home > Back-end >  Python: Will A List Changing Size During 'not in' Cause UB?
Python: Will A List Changing Size During 'not in' Cause UB?

Time:10-03

I have a hypothetical program with two threads.

items = [ 'A', 'B' ]


func1():
    while True:
        if 'C' not in items:
            # do something
        
func2():
    while True:
        items.clear()
        items.append('A')
        items.append('B')

main():
    start_new_thread(func1)
    start_new_thread(func2)

When not in is executed, I assume Python must internally iterate over the list to check each element. If func2 changes the size of this list during the iteration, will it cause an exception or UB?

CodePudding user response:

You should never allow two threads to access the same piece of memory, at the same time, in any programming language, ever. This creates a data race condition which leads to extremely undefined behavior (If your programming language of choice cannot detect this and throw an exception). The safest thing to do is use a lock object to force the execution of a thread to stop if another thread has acquired the lock, and wait until it is safe to modify the data again. Here is your minimal example with locks added (and also modified to be actual working code).

import threading

items = [ 'A', 'B' ]
lock = threading.Lock()

def func1():
    while True:
        lock.acquire()
        if 'C' not in items:
            print("C not in items")
        lock.release()

def func2():
    while True:
        lock.acquire()
        items.clear()
        items.append('A')
        items.append('B')
        lock.release()

def main():
    thread_a = threading.Thread(target=func1, daemon=True)
    thread_b = threading.Thread(target=func2, daemon=True)
    thread_a.start()
    thread_b.start()
    thread_a.join()
    thread_b.join()

main()

Note that many libraries may refer to some of their functions as being "thread safe". This means that they already handled any potential data race conditions and you do not have to worry about setting up locks. You may also encounter "atomic" operations, which basically just means that they are thread-safe operations. Atomic operations aren't really a thing in python though.

  • Related