Search code examples
python-3.xrandomglobal-variablespython-multithreading

How can I make this multithreaded?


I made a Python script that simulates a dice and then calculates the relative frequency.

I thought, why not making it multithreaded? Now I'm stuck with the variables. If I run this, it's like the last thread overrides all other results, so it will run multithreaded but only the result of the last thread's taken. Modify the variable tries to your needs, it's set to 8 so you see that there were only 2 random numbers taken and calculated to percent at the end. Don't modify NrThreads, because it always starts 4.

import threading
import random


### CONFIGURE
tries=8
NrThreads=4
triesThread=round(round(tries)/4)
###\CONFIGURE

def ThreadCode():
    global one
    global two
    global three
    global four
    global five
    global six
    one=0
    two=0
    three=0
    four=0
    five=0
    six=0
    for i in range(0, triesThread):
        number=random.randint(1,6)
        if (number == 1):
            one=one+1
        if (number == 2):
            two=two+1
        if (number == 3):
            three=three+1
        if (number == 4):
            four=four+1
        if (number == 5):
            five=five+1
        if (number == 6):
            six=six+1

thread1 = threading.Thread(target=ThreadCode)
thread1.start()
print("Started thread")
thread2 = threading.Thread(target=ThreadCode)
thread2.start()
print("Started thread")
thread3 = threading.Thread(target=ThreadCode)
thread3.start()
print("Started thread")
thread4 = threading.Thread(target=ThreadCode)
thread4.start()
print("Started thread")
thread1.join()
thread2.join()
thread3.join()
thread4.join()

print("Number 1: ", one)
print("Number 2: ", two)
print("Number 3: ", three)
print("Number 4: ", four)
print("Number 5: ", five)
print("Number 6: ", six)

p1=one/tries
print("Probability for number 1: ", p1)

for i in ([one, two, three, four, five, six]):
    print(i/tries,"  ", i/tries*100,"%")

Solution

  • You code has a few issues:

    1. You reset the numbers to 0 in every thread. Every time the function enters they go back to 0.
    2. Your code isn't thread safe. You can't use += from multiple threads on the same number, otherwise it'll overwrite eachother.

    Keep in mind this code won't actually be faster because Python has a Global Interpreter Lock (GIL) and you need a lock on all of the additions anyway.

    Here's the fixed code:

    import threading
    import random
    
    
    ### CONFIGURE
    tries=8
    NrThreads=4
    triesThread=round(tries/4)
    ###\CONFIGURE
    
    lock = threading.Lock()
    one=0
    two=0
    three=0
    four=0
    five=0
    six=0
    
    def ThreadCode():
        global one
        global two
        global three
        global four
        global five
        global six
        for i in range(0, triesThread):
            number=random.randint(1,6)
            with lock:
                match number:
                    case 1:
                        one += 1
                    case 2:
                        two += 1
                    case 3:
                        three += 1
                    case 4:
                        four += 1
                    case 5:
                        five += 1
                    case 6:
                        six += 1
    
    thread1 = threading.Thread(target=ThreadCode)
    thread1.start()
    print("Started thread")
    thread2 = threading.Thread(target=ThreadCode)
    thread2.start()
    print("Started thread")
    thread3 = threading.Thread(target=ThreadCode)
    thread3.start()
    print("Started thread")
    thread4 = threading.Thread(target=ThreadCode)
    thread4.start()
    print("Started thread")
    thread1.join()
    thread2.join()
    thread3.join()
    thread4.join()
    
    print("Number 1: ", one)
    print("Number 2: ", two)
    print("Number 3: ", three)
    print("Number 4: ", four)
    print("Number 5: ", five)
    print("Number 6: ", six)
    
    p1=one/tries
    print("Probability for number 1: ", p1)
    
    for i in ([one, two, three, four, five, six]):
        print(i/tries,"  ", i/tries*100,"%")