Judking
Judking

Reputation: 6371

why does the thread number increase over the setting of threading.BoundedSemaphore in python?

Here's the code:

import time
from threading import Thread
import threading

class Test:
    #set the max thread number
    threadLimiter = threading.BoundedSemaphore(10)

    def go(self):
        lstRecordThreads = []
        for i in range(1, 200):
            Test.threadLimiter.acquire()
            try:
                recordThread = Thread(target=self.recordExec, args=(i,))
                recordThread.start()
                time.sleep(0.25);
                lstRecordThreads.append(recordThread)
            finally:
                Test.threadLimiter.release()

        for rt in lstRecordThreads:
            rt.join()

    def recordExec(self, number):
        print "current number=["+str(number)+"]"
        time.sleep(12);
        print "done=["+str(number)+"]";

t = Test()
t.go()

But the result is that the thread number is not limited by the number setting in BoundedSemaphore. Could anyone give me an explanation on this scenario?

Why doesn't the main thread hang up at code Test.threadLimiter.acquire() when current sub thread number is already 10? Thanks a lot!

Upvotes: 0

Views: 494

Answers (2)

flyer
flyer

Reputation: 9816

As @Tim Peters says, in your main thread, you acquire a semaphore, create a thread, release the semaphore and repeat this procedure 200 times which never decreases the number of semaphores to 0.

If you want to control the number of threads created, in the main thread, you should acquire a semaphore firstly and then create a thread. At the end of the the thread routine, release the semaphore rather than done by the main thread.

Here is the modification:

#!/usr/bin/env python2.7
#coding: utf-8

import threading
import time


class Test:
    #set the max thread number
    threadLimiter = threading.BoundedSemaphore(10)

    def go(self):
        lstRecordThreads = []
        for i in range(1, 200):
            Test.threadLimiter.acquire()
            recordThread = threading.Thread(target=self.recordExec, args=(i,))
            recordThread.start()
            lstRecordThreads.append(recordThread)

        for rt in lstRecordThreads:
            rt.join()

    def recordExec(self, number):
        print "current number=["+str(number)+"]"
        time.sleep(1)
        print "done=["+str(number)+"]"
        print('Active thread count: %d' % (threading.active_count(),))        
        Test.threadLimiter.release()


if __name__ == '__main__':
    t = Test()
    t.go()

Upvotes: 2

Tim Peters
Tim Peters

Reputation: 70602

There's no reason to believe the semaphore isn't working. What's unclear is why you think it isn't. Your main loop doesn't wait for anything - it fires off threads as fast as it can, sleeping a quarter of a second between tries. On each iteration it releases the sempahore. So:

acquire sempahore
create a thread
sleep 0.25 seconds
release sempahore

acquire semaphore
create a thread
sleep 0.25 seconds
release sempahore

etc etc etc. In fact, the semaphore count never goes below 9! Every time you acquire it, you release it before you try to acquire it again.

Sorry, but can't guess what you intended to do.

Upvotes: 0

Related Questions