Stratos Ion
Stratos Ion

Reputation: 628

Python threads are not closing after join

I am using a similar code as bellow to control an rgb led strip, random values come in every few seconds and 3 threads are being created to control the 3 individual colours.

import time
from ast import literal_eval
import threading
from random import randint
t=[]
myR =0
myG =0
myB =0
temp = 0
pins = [17,22,24]
myColours = [myR,myG,myB]
red_pin = 17
green_pin = 22
blue_pin = 24

def change_led_color(rgb):
  global myR
  global myG
  global myB
  y = 0
  threads = []
  for colour in rgb:
    t = threading.Thread(target=leds,name=pins[y] ,args=(y,myColours[y],colour,pins[y]))
    threads.append(t)
    y += 1
  for y in threads:
    y.start()
  for y in threads:
    y.join()

def leds(index,start,end,pin):
  temp=0
  for i in range(start,end):
    time.sleep(0.01)
    temp = i
  global myColours
  print 'pin', pin, 'started at: ',start,' ended is: ', temp
  myColours[index] = end

def set_colours():
  print '..................................................................',t
  print threading.activeCount(),'threads \n'
  threading.Timer(2, set_colours).start()
  change_led_color(t)
set_colours()

def get_data():
  while True:
      global t
      t = (randint(0,255),randint(0,255),randint(0,255))
      time.sleep(2)
threading.Thread(target=get_data).start()

The above runs fine but the responses are very weird, instead of getting all the three colours at the end of the threads, I sometimes get more than expected and most of the times at least one will be 0, like the thread never run! I am assuming I'm misusing the threading in some way..

e.g. outcome

.................................................................. (187, 223, 42)
3 threads 

pin 24 started at:  205  ended is:  0
pin 22 started at:  170  ended is:  222
pin 17 started at:  107  ended is:  186
.................................................................. (202, 115, 219)
3 threads 

pin 22 started at:  223  ended is:  0
pin 17 started at:  187  ended is:  201
.................................................................. (244, 35, 194)
5 threads 

pin 22 started at:  115  ended is:  0
pin 24 started at:  42  ended is:  218
pin 17 started at:  202  ended is:  243
pin 24 started at:  42  ended is:  193
.................................................................. (54, 25, 72)
3 threads 

pin 17 started at:  244  ended is:  0
pin 22 started at:  35  ended is:  0
 pin 24 started at:  194  ended is:  0

Upvotes: 1

Views: 1413

Answers (2)

rob
rob

Reputation: 37644

Without taking into account other factors (see below) the for i in range(start,end): loop will last up to 2.5 seconds; but you actually spawn new threads every 2 seconds.

Moreover, the actual duration of that loop is actually even longer:

  • Whenever you ask for a sleep, the duration is at least what you have asked; but it could be slightly more. Especially when you ask for 1/100 of a second, it might be a bit longer.
  • Since you are asking for many small sleep one after the other, you might expect that the effects get multiplied; meaning that the total time spent in the loop for i in range(start,end): will be longer than expected

Try to:

  • Use a single wait: time.sleep(0.01 * start-end if end>start else 0)
  • Increase the time used to spawn new threads to 3-4 seconds

Upvotes: 1

Tejas
Tejas

Reputation: 165

Have you considered GIL (Global Interpreter lock)? https://wiki.python.org/moin/GlobalInterpreterLock

Python has a GIL which doesn't allow multiple threads to run from a single process. When you run your code, it is run as a python process. You are trying to launch threads from same process which is not permitted in python.

If you want to perform some operations in parallel, multiprocessing package is a good option.
https://pymotw.com/2/multiprocessing/basics.html

Upvotes: 1

Related Questions