Lock and queue

Deadlock

- 指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程 
from threading import Thread
import time
mutexA = Lock()
mutexB = Lock()

class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()
      def func1(self):
        mutexA.acquire()
        print('\033[41m%s 拿到A锁\033[0m' %self.name)
        mutexB.acquire()
        print('\033[42m%s 拿到B锁\033[0m' %self.name)
        mutexB.release()
        mutexA.release()
    def func2(self):
        mutexB.acquire()
        print('\033[43m%s 拿到B锁\033[0m' %self.name)
        time.sleep(2)
        mutexA.acquire()
        print('\033[44m%s 拿到A锁\033[0m' %self.name)
        mutexA.release()
        mutexB.release()
if __name__ == '__main__':
    for i in range(10):
        t = MyThread()
        t.start()
Thread-1 拿到A锁        
Thread-1 拿到B锁
Thread-1 拿到B锁
Thread-2 拿到A锁 #出现死锁,整个程序阻塞住

Recursive lock:

-  解决死递归方法  --- python提供了可重入锁RLock 
-   RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源 
-   区别是:递归锁可以连续acquire多次,而互斥锁只能acquire一次 
from threading import Thread
import time
mutexA = mutexB = RLock()
#一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止

class MyThread(Theard):
    def run(self):
        self.func1()
        self.func2()
    def func1(self):
        mutexA.acquire()
        print('\033[41m%s 拿到A锁\033[0m' %self.name)
        mutexB.acquire()
        print('\033[42m%s 拿到B锁\033[0m' %self.name)
        mutexB.release()
        mutexA.release()
    def func2(self):
        mutexB.acquire()
        print('\033[43m%s 拿到B锁\033[0m' %self.name)
        time.sleep(2)
        mutexA.acquire()
        print('\033[44m%s 拿到A锁\033[0m' %self.name)
        mutexA.release()
        mutexB.release()
if __name__ == '__main__':
    for i in range(10):
        t=MyThread()
        t.start()    

Semaphore ---- Semaphore

- Semaphore is a lock, you can specify the semaphore of 5, compared to the same time a mutex only one task to perform to grab the lock, semaphore at the same time can have five tasks to perform to get the lock, if the mutual exclusion lock is shared houses who try to steal a toilet, then the signal is equivalent to the amount of competition for a group of passers public toilets, pit latrines have more bits, which means that at the same time can have multiple personal public toilets, public toilets to accommodate the number is certain, this is the size of the semaphore
from threading import Thraad
import threading
import time

def func():
    sm.acquire()
    print(f'{threading} get sm')
    time.sleep(2)
    sm.release()
if __name__ =='__main__':
    sm = Semaphore(5)
    for i in ranfe(25):
        t = Thread(target= func)
        t.satrt()
        
Semaphore管理一个内置的计数器,
每当调用acquire()时内置计数器-1;
调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。        

Event :

-  线程的一个关键特性是每个线程都是独立运行且状态不可预测 
-   threading库中的Event对象。 对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在 初始情况下,Event对象中的信号标志被设置为假。如果有线程等待一个Event对象, 而这个Event对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真,它将唤醒所有等待这个Event对象的线程。如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件, 继续执行 
from threading import Event

event.isSet()  # 返回event的的状态值

event.wait()  #如果 event.isSet()==False将阻塞线程

event.set(): #设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;

event.clear():#恢复event的状态值为False。

#定时器,指定n秒后执行某操作

from threading import Timer

def hello():
    print('hello world')
    
t = Timer(1,hello)
t.start()   # after 1 seconds, "hello, world" will be printed

Thread Q [queue]:

  • class queue.Queue (maxsize) # queue: FIFO

import queue

q = queue.Queue()
q.put('first')
q.put('second')

print(q.get())
print(q.get())

first 
second

-class queue.LifoQueue (maxsize = 0) # Stack last in first out, last out

import queue
q= queue.LifoQueue()

q.put('first')
q.put('second')

print(q.get())
print(q.get())

#后进先出
second  / first

class queue.PriorityQueue (maxsize = 0) # priority queue: store data may be provided a priority queue, in accordance with the smaller number ascii, executed sooner

import queue
q = queue.PriortyQueu()
q.put((20,'q'))
q.put((10,'b'))

ptiny(q.get())
ptiny(q.get())

1.首先根据第一个参数判断ascii表的数值大小
2.判断第个参数中的汉字顺序.
3.再判断第二参数中数字--> 字符串数字 ---> 中文
4.以此类推
多线程的作用:
    站在两个角度去看问题:

    - 四个任务, 计算密集型, 每个任务需要10s:
        单核:
            - 开启进程
                消耗资源过大
                - 4个进程: 40s

            - 开启线程
                消耗资源远小于进程
                - 4个线程: 40s

        多核:
            - 开启进程
                并行执行,效率比较高
                - 4个进程: 10s

            - 开启线程
                并发执行,执行效率低.
                - 4个线程: 40s



    - 四个任务, IO密集型, 每个任务需要10s:
        单核:
            - 开启进程
                消耗资源过大
                - 4个进程: 40s

            - 开启线程
                消耗资源远小于进程
                - 4个线程: 40s

        多核:
            - 开启进程
                并行执行,效率小于多线程,因为遇到IO会立马切换CPU的执行权限
                - 4个进程: 40s  +  开启进程消耗的额外时间

            - 开启线程
                并发执行,执行效率高于多进程

                - 4个线程: 40s

to sum up:

在计算密集型的情况下:
    使用多进程
    
在IO密集型的情况下:
    使用多线程
    
高效执行多个进程,内多个IO密集型的程序

Guess you like

Origin www.cnblogs.com/shaozheng/p/11728094.html