Print zero and even numbers-Event, Semaphore, Lock

Print zeros and odd and even numbers

Suppose there is such a class:

class ZeroEvenOdd {
    
    
  public ZeroEvenOdd(int n) {
    
     ... }      // 构造函数
  public void zero(printNumber) {
    
     ... }  // 仅打印出 0
  public void even(printNumber) {
    
     ... }  // 仅打印出 偶数
  public void odd(printNumber) {
    
     ... }   // 仅打印出 奇数
}

The same instance of the ZeroEvenOdd class will be passed to three different threads:

Thread A will call zero(), which will only output 0.
Thread B will call even(), which will only output even numbers.
Thread C will call odd(), which will only output odd numbers.
Each thread has a printNumber method to output an integer. Please modify the code given to output the integer sequence 010203040506..., where the length of the sequence must be 2n.

Example 1:
Input: n = 2
Output: "0102"
Description: Three threads execute asynchronously, one of which calls zero(), another thread calls even(), and the last thread calls odd(). The correct output is "0102".

Example 2:
Input: n = 5
Output: "0102030405"

analysis

Since there are two threads that alternate, first think of 1 semaphore and 2 events: different events trigger different threads, and only one thread is allowed to execute (semaphore) at a time.

In the two alternately executed threads, no matter which thread is executed, the zero thread will definitely be executed, so there is a mechanism to control the zero thread execution in these two alternately executed threads. (lock)

At the beginning of the program, the zero thread is called for execution first, so at the beginning, the zero thread acquires the mutex lock, releases a resource, and then a mechanism composed of two events determines that the resource is allocated to the two threads currently executing alternately Which one, and the zero thread is blocked at this time, waiting for the alternate execution thread to release the lock.


solution

from threading import Semaphore, Lock, Event, Thread, current_thread
class ZeroEvenOdd:
    def __init__(self, n):
        self.n = n
        self.s = Semaphore(0)
        self.lock = Lock()
        # 初始化两个事件,控制两个事件的有序性,初始时事件是false
        self.event_odd = Event()
        self.event_even = Event()
        # 先发生的是奇数事件
        self.event_odd.set()
        
	# printNumber(x) outputs "x", where x is an integer.
    def zero(self, printNumber: 'Callable[[int], None]') -> None:
        for i in range(self.n):
            # 获取锁
            self.lock.acquire()
            # printNumber
            printNumber(0)
            print(current_thread().name)
            # 释放一个资源
            self.s.release()
        
    def even(self, printNumber: 'Callable[[int], None]') -> None:
        for i in range(2, self.n+1, 2):
            # 等待事件的发生,才能够获取资源
            self.event_even.wait()
            # 等待资源
            self.s.acquire()
            # printNumber
            printNumber(i)
            print(current_thread().name)
            # 结束当前事件
            self.event_even.clear()

            # 释放锁
            self.lock.release()
            # 触发另一个事件
            self.event_odd.set()

    def odd(self, printNumber: 'Callable[[int], None]') -> None:
        for i in range(1, self.n+1, 2):
            # 等待事件的发生,才能够获取资源
            self.event_odd.wait()
            # 等待资源
            self.s.acquire()
            # printNumber
            printNumber(i)
            print(current_thread().name)
            # 结束当前事件
            self.event_odd.clear()
            # 释放锁
            self.lock.release()
            # 触发另一个事件
            self.event_even.set()


# running 
obj = ZeroEvenOdd(2)

thread1 = Thread(target=obj.zero,args=(print,))

thread2 = Thread(target=obj.odd,args=(print,))
thread3 = Thread(target=obj.even,args=(print,))
thread1.start()
thread2.start()
thread3.start()

Guess you like

Origin blog.csdn.net/qq_39378657/article/details/109618054