HungCung
HungCung

Reputation: 188

Does Lock object in python 2 have time out?

I'm learning multithread in python. I write some code to practice it

import threading
import time

Total = 0
class myThead(threading.Thread):

    def __init__(self, num):
        threading.Thread.__init__(self)
        self.num = num
        self.lock = threading.Lock()
    def run(self):
        global Total
        self.lock.acquire()
        print "%s acquired" % threading.currentThread().getName()
        for i in range(self.num):
            Total += 1
        print Total
        print "%s released" % threading.currentThread().getName()
        self.lock.release()

t1 = myThead(100)
t2 = myThead(100)
t1.start()
t2.start()

if i pass 100 to thread t1 and t2, they go correctly.

Thread-1 acquired
100
Thread-1 released
Thread-2 acquired
200
Thread-2 released

But when i try with bigger numbler. For example, i pass 10000. It prints out unexpected output.

Thread-1 acquired
Thread-2 acquired
14854
Thread-1 released
15009
Thread-2 released

I try many times but no thing changes. So i think Lock object in python have timeout. If Lock acquire for long time, it will allow other thread can go. Can anyone explain me about it. Thank you!

Upvotes: 1

Views: 425

Answers (2)

AnkhMorporkian
AnkhMorporkian

Reputation: 31

No, locks do not have a timeout. What is happening is that they are not actually sharing the same lock, as a new one is created every time you instantiate the object in the init method. If all instances of that class will always share the same lock, then you could throw it in as a class property. However, explicit is better than implicit. I would personally put the lock as an argument in the init method. Something like this.

import threading
import time

Total = 0
class myThead(threading.Thread):

    def __init__(self, num, lock):
        threading.Thread.__init__(self)
        self.num = num
        self.lock = lock


    def run(self):
        global Total
        self.lock.acquire()
        print "%s acquired" % threading.currentThread().getName()
        for i in range(self.num):
            Total += 1
        print Total
        print "%s released" % threading.currentThread().getName()
        self.lock.release()

threadLock = threading.Lock()
t1 = myThead(100, threadLock)
t2 = myThead(100, threadLock)
t1.start()
t2.start()

That way both instances of the class share the same lock.

Upvotes: 3

Kevin
Kevin

Reputation: 76234

Each thread gets its own lock, so acquiring t1's lock doesn't stop t2 from acquiring its own lock.

Perhaps you could make lock a class attribute, so all instances of myThread share one.

class myThead(threading.Thread):
    lock = threading.Lock()

    def __init__(self, num):
        threading.Thread.__init__(self)
        self.num = num

Result:

Thread-1 acquired
10000
Thread-1 released
Thread-2 acquired
20000
Thread-2 released

Upvotes: 2

Related Questions