ficapy
3/12/2018 - 8:17 AM

多线程锁 https://www.ficapy.com/2018/03/12/Python_Thread_Lock/

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: ficapy
# Create: '12/03/2018'

from threading import Lock, get_ident


class RLock:

    def __init__(self):
        self.lock = Lock()
        self._owner = None
        self._count = 0

    def acquire(self):
        me = get_ident()
        if self._owner == me:
            self._count += 1
            return
        rc = self.lock.acquire()
        if rc:
            self._owner = me
            self._count = 1

    __enter__ = acquire

    def release(self):
        if self._owner != get_ident():
            raise RuntimeError()
        self._count -= 1
        if self._count == 0:
            self._owner = None
            self.lock.release()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.release()


from collections import deque


class Condition:

    def __init__(self):
        self._lock = RLock()
        self._waiters = deque()

    def __enter__(self):
        return self._lock.__enter__()

    def __exit__(self, *args):
        return self._lock.__exit__(*args)

    def wait(self):
        assert get_ident() == self._lock._owner
        waiter = Lock()
        self._waiters.append(waiter)

        waiter.acquire()
        self._lock.release()
        waiter.acquire()
        self._lock.acquire()
        del waiter

    def notify(self):
        assert get_ident() == self._lock._owner
        for waiter in self._waiters.copy():
            waiter.release()
            self._waiters.remove(waiter)


class Semaphore:
    def __init__(self, value=1):
        self._lock = Condition()
        self.value = value

    def __enter__(self):
        with self._lock:
            if self.value == 0:
                self._lock.wait()
            else:
                self.value -= 1

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.value += 1
        self._lock.notify()


class BoundedSemaphore(Semaphore):
    def __init__(self, value=1):
        super(BoundedSemaphore, self).__init__(value=value)


class Event:
    def __init__(self):
        self._cond = Condition()
        self._flag = False

    def set(self):
        with self._cond:
            self._flag = True
            self._cond.notify()

    def clear(self):
        with self._cond:
            self._flag = False

    def wait(self):
        with self._cond:
            signaled = self._flag
            if not signaled:
                signaled = self._cond.wait()
            return signaled