Home > Blockchain >  How to run multiple threads alternately in Python?
How to run multiple threads alternately in Python?

Time:11-27

I'm trying to run 2 threads below alternately:

import threading

def test1():
    for _ in range(3):
        print("Test1")
    
def test2():
    for _ in range(3):
        print("Test2")

t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)

t1.start()
t2.start()

t1.join()
t2.join()

But, the result is as shown below:

Test1
Test1
Test1
Test2
Test2
Test2

I want the result as shown below:

Test1
Test2
Test1
Test2
Test1
Test2

Are there any ways to do that?

CodePudding user response:

You can get the alternate result with a global variable, lock and while statement as shown below:

import threading
owner = "Test1"
lock = threading.Lock()

def test1():
    global owner
    i = 0
    while i < 3:
        lock.acquire()
        if owner == "Test1":
            print("Test1")
            owner = "Test2"
            i  = 1
        lock.release()

def test2():
    global owner
    i = 0
    while i < 3:
        lock.acquire()
        if owner == "Test2":
            print("Test2")
            owner = "Test1"
            i  = 1
        lock.release()

t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)

t1.start()
t2.start()

t1.join()
t2.join()

Then, you can get the alternate result below:

Test1
Test2
Test1
Test2
Test1
Test2

You can also get the alternate result with a queue, lock and while statement as shown below:

import queue
import threading
lock = threading.Lock()

def test1(owner):
    i = 0
    while i < 3:
        lock.acquire()
        if owner.queue[0] == "Test1":
            print("Test1")
            owner.queue[0] = "Test2"
            i  = 1
        lock.release()

def test2(owner):
    i = 0
    while i < 3:
        lock.acquire()
        if owner.queue[0] == "Test2":
            print("Test2")
            owner.queue[0] = "Test1"
            i  = 1
        lock.release()
        
owner = queue.Queue()
owner.put("Test1")

t1 = threading.Thread(target=test1, args=(owner,))
t2 = threading.Thread(target=test2, args=(owner,))

t1.start()
t2.start()

t1.join()
t2.join()

Then, you can get the alternate result below:

Test1
Test2
Test1
Test2
Test1
Test2

CodePudding user response:

I think your question here is about why the two functions are not executed simultaneously, but rather in sequence. The answer is that Python has a global interpreter lock (GIL). A single Python process will not (normally) run Python code in multiple parallel threads. There are exceptions to this, such as when running native code (in which case the GIL may be released).

In your trivial example there would be no need for threading of course. In a real world scenario the problem is actually less of a problem. Typically, CPU intensive tasks are offloaded to a native library (such as Pytorch, Numpy, Scipy, Pandas etc) all which are written in native code or has parallelization built in.

If you find yourself writing code that would be solved by utilizing multiple CPU cores to interpret Python code, there is most likely a better solution to your problem.

That said, have a look at the multiprocessing module, which can run multiple Python functions in parallel by utilizing multiple processes and parallel primitives (such as queues and map-reduce)

  • Related