LeetCode算法题整理(并发篇)Threading

1114. Print in Order

按照指定的顺序打印,三个线程的方法。

方法一:Lock 锁对象法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from threading import Lock

class Foo:
def __init__(self):
self.locks = (Lock(),Lock())
self.locks[0].acquire()
self.locks[1].acquire()

def first(self, printFirst):
printFirst()
self.locks[0].release()

def second(self, printSecond):
with self.locks[0]:
printSecond()
self.locks[1].release()


def third(self, printThird):
with self.locks[1]:
printThird()

方法二:信号量。Semaphore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from threading import Semaphore

class Foo:
def __init__(self):
self.gates = (Semaphore(0),Semaphore(0))

def first(self, printFirst):
printFirst()
self.gates[0].release()

def second(self, printSecond):
with self.gates[0]:
printSecond()
self.gates[1].release()

def third(self, printThird):
with self.gates[1]:
printThird()

方法三:Event事件对象法。原理同上,用wait方法作为阻塞,用set来释放线程,默认类赋值就是阻塞的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import threading

class Foo:
def __init__(self):
self.e1 = threading.Event()
self.e2 = threading.Event()

def first(self, printFirst: 'Callable[[], None]') -> None:
printFirst()
self.e1.set()

def second(self, printSecond: 'Callable[[], None]') -> None:
self.e1.wait()
printSecond()
self.e2.set()

def third(self, printThird: 'Callable[[], None]') -> None:
self.e2.wait()
printThird()

方法四:Barrier障碍法。Barrier初始化的时候定义了parties = 2个等待线程,调用完了partieswait就会释放线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import threading

class Foo:
def __init__(self):
self.b1 = threading.Barrier(2)
self.b2 = threading.Barrier(2)

def first(self, printFirst: 'Callable[[], None]') -> None:
printFirst()
self.b1.wait()

def second(self, printSecond: 'Callable[[], None]') -> None:
self.b1.wait()
printSecond()
self.b2.wait()

def third(self, printThird: 'Callable[[], None]') -> None:
self.b2.wait()
printThird()

方法五:队列法。直接使用多线程专用的阻塞队列,对于队列为空时,get方法就会自动阻塞,直到put使之非空才会释放进程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import queue

class Foo:
def __init__(self):
self.q1 = queue.Queue()
self.q2 = queue.Queue()

def first(self, printFirst: 'Callable[[], None]') -> None:
printFirst()
self.q1.put(0)

def second(self, printSecond: 'Callable[[], None]') -> None:
self.q1.get()
printSecond()
self.q2.put(0)

def third(self, printThird: 'Callable[[], None]') -> None:
self.q2.get()
printThird()

方法六:反过来,对于定容队列来说,如果队列满了,put方法也是阻塞。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import queue

class Foo:
def __init__(self):
self.q1 = queue.Queue(1)
self.q1.put(0)
self.q2 = queue.Queue(1)
self.q2.put(0)

def first(self, printFirst: 'Callable[[], None]') -> None:
printFirst()
self.q1.get()

def second(self, printSecond: 'Callable[[], None]') -> None:
self.q1.put(0)
printSecond()
self.q2.get()

def third(self, printThird: 'Callable[[], None]') -> None:
self.q2.put(0)
printThird()

方法七:Condition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from threading import Condition

class Foo:
def __init__(self):
self.exec_condition = Condition()
self.order = 0
self.first_finish = lambda: self.order == 1
self.second_finish = lambda: self.order == 2

def first(self, printFirst):
with self.exec_condition:
printFirst()
self.order = 1
self.exec_condition.notify(2)

def second(self, printSecond):
with self.exec_condition:
self.exec_condition.wait_for(self.first_finish)
printSecond()
self.order = 2
self.exec_condition.notify()

def third(self, printThird):
with self.exec_condition:
self.exec_condition.wait_for(self.second_finish)
printThird()