Python 多线程-线程的同步锁&死锁

并发:指的是系统具有执行多个任务(动作)的能力

并行:指的是系统具有同时执行多个任务(动作)的能力, 也就是同一时刻执行多个任务。(同一时刻)

 

同步:当执行一个IO操作的时候(等待一个外部数据的时候),等待

异步:当执行一个IO操作的时候(等待一个外部数据的时候),不等待,继续执行其他,直到接收到外部数据的时候再回来处理

 

 

多线程带来的数据混乱问题:

import threading
import time



ticket = 100
def sally_ticket():
    """
        当多个线程同时得到 temp =ticket后,此时大家得到的数是一样的; 然后发送阻塞,当有一个线程结束阻塞后将ticket-1,
        此时 ticket已经发生变化,但是其他还没有完成阻塞的线程拿到的temp还没有改变,这样就造成数据混乱了。
    :return:
    """
    global ticket
    temp = ticket
    time.sleep(0.001)
    ticket = temp - 1


if __name__ == '__main__':
    threads = []
    for i in range(100):
        t = threading.Thread(target=sally_ticket, args=())
        t.start()
        threads.append(t)

    for t in threads:
        t.join()

    print(ticket)

 

解决办法,加同步锁(将需要操作共同数据的代码块保护起来,使之变成串行)

import threading
import time


ticket = 100
lock=threading.Lock() # 得到锁
def sally_ticket():

    global ticket
    lock.acquire()  # 加锁
    temp = ticket
    time.sleep(0.01)
    ticket = temp - 1
    lock.release()  # 解锁


if __name__ == '__main__':
    threads = []
    for i in range(100):
        t = threading.Thread(target=sally_ticket, args=())
        t.start()
        threads.append(t)

    for t in threads:
        t.join()

    print(ticket)

 

死锁:

  在线程之间共享资源的时候,双方的锁均没有被释放,各自等待对方的锁释放。

import threading
import time

class MyThread(threading.Thread):

    def __init__(self, thread_name):
        threading.Thread.__init__(self)
        self.thread_name = thread_name

    def action1(self):
        lock1.acquire()
        print('%s 拿到 lock1锁' % self.thread_name)
        time.sleep(2)
        lock2.acquire()
        print('%s 拿到 lock2锁' % self.thread_name)
        time.sleep(2)

        lock1.release()
        lock2.release()

    def action2(self):
        lock2.acquire()
        print('%s 拿到 lock2锁' % self.thread_name)
        time.sleep(2)
        lock1.acquire()
        print('%s 拿到 lock1锁' % self.thread_name)
        time.sleep(2)

        lock2.release()
        lock1.release()

    def run(self):
        self.action1()
        self.action2()


if __name__ == '__main__':
    lock1 = threading.Lock()
    lock2 = threading.Lock()

    threads = []

    for i in range(5):
        t = MyThread('thread%s'%i)
        t.start()
        threads.append(t)
    for i in threads:
        i.join()

    print('==========================================')

 

 

解决方法使用递归锁:

  递归锁,就是只有一把锁,这把锁每次加锁的时候里面的计数器就加1,直到里面的计算器清零(释放锁),其他的线程才可以得到这把递归锁。

import threading
import time

class MyThread(threading.Thread):

    def __init__(self, thread_name):
        threading.Thread.__init__(self)
        self.thread_name = thread_name

    def action1(self):
        lock.acquire()
        print('%s 拿到 lock锁' % self.thread_name)
        time.sleep(2)
        lock.acquire()
        print('%s 拿到 lock锁' % self.thread_name)
        time.sleep(2)

        print('%s 释放 lock锁' % self.thread_name)
        lock.release()
        print('%s 释放 lock锁' % self.thread_name)
        lock.release()

    def action2(self):
        lock.acquire()
        print('%s 拿到 lock锁' % self.thread_name)
        time.sleep(2)
        lock.acquire()
        print('%s 拿到 lock锁' % self.thread_name)
        time.sleep(2)

        print('%s 释放 lock锁' % self.thread_name)
        lock.release()
        print('%s 释放 lock锁' % self.thread_name)
        lock.release()

    def run(self):
        self.action1()
        self.action2()


if __name__ == '__main__':
    lock= threading.RLock() # 递归锁

    threads = []

    for i in range(5):
        t = MyThread('thread%s'%i)
        t.start()
        threads.append(t)
    for i in threads:
        i.join()

    print('==========================================')

 

posted @ 2021-01-09 11:21  leungqingyun  阅读(77)  评论(0编辑  收藏  举报