Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #32065 > unrolled thread

Re: A lock that prioritizes acquire()s?

Started byIan Kelly <ian.g.kelly@gmail.com>
First post2012-10-24 14:19 -0600
Last post2012-10-24 14:19 -0600
Articles 1 — 1 participant

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: A lock that prioritizes acquire()s? Ian Kelly <ian.g.kelly@gmail.com> - 2012-10-24 14:19 -0600

#32065 — Re: A lock that prioritizes acquire()s?

FromIan Kelly <ian.g.kelly@gmail.com>
Date2012-10-24 14:19 -0600
SubjectRe: A lock that prioritizes acquire()s?
Message-ID<mailman.2794.1351110001.27098.python-list@python.org>
On Wed, Oct 24, 2012 at 12:54 PM, David M Chess <chess@us.ibm.com> wrote:
> Seeking any thoughts on other/better ways to do this, or whether the
> inefficiency will be too eyerolling if we get say one request per second
> with an average service time a bit under a second but maximum service time
> well over a second, and most of them are importance zero, but every (many)
> seconds there will be one or two with higher importance.

I used a PriorityQueue and Conditions to get rid of the ugly while True loop.


import threading
from Queue import PriorityQueue, Empty

class PriorityLock(object):

    def __init__(self):
        self._is_available = True
        self._mutex = threading.Lock()
        self._waiter_queue = PriorityQueue()

    def acquire(self, priority=0):
        self._mutex.acquire()
        # First, just check the lock.
        if self._is_available:
            self._is_available = False
            self._mutex.release()
            return True
        condition = threading.Condition()
        condition.acquire()
        self._waiter_queue.put((priority, condition))
        self._mutex.release()
        condition.wait()
        condition.release()
        return True

    def release(self):
        self._mutex.acquire()
        # Notify the next thread in line, if any.
        try:
            _, condition = self._waiter_queue.get_nowait()
        except Empty:
            self._is_available = True
        else:
            condition.acquire()
            condition.notify()
            condition.release()
        self._mutex.release()

def test():
    import random, time

    def thread(lock, priority):
        lock.acquire(priority)
        print("Thread %d running" % priority)
        time.sleep(1)
        lock.release()
    lock = PriorityLock()
    threads = [threading.Thread(target=thread, args=(lock, x)) for x
in range(10)]
    random.shuffle(threads)
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()

if __name__ == "__main__":
    test()


Output:

Thread 9 running
Thread 0 running
Thread 1 running
Thread 2 running
Thread 3 running
Thread 4 running
Thread 5 running
Thread 6 running
Thread 7 running
Thread 8 running

Note that with the PriorityQueue, lower priority values are retrieved
first.  Thread 9 ran first just by virtue of being first to the gate,
and after that you can see that everything went in order.

Cheers,
Ian

[toc] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web