zoukankan      html  css  js  c++  java
  • (9)开启线程的互斥锁

    使用互斥锁

    from threading import Thread,Lock #从threading包内倒入Lock模块

    mutex = Lock() #定义锁
    x = 100
    def task():
    global x
    mutex.acquire() # 获得锁
    temp = x
    x = temp - 1
    mutex.release() # 释放锁
    if __name__ == '__main__':
    t_l = []
    for i in range(100):
    t = Thread(target=task)
    t_l.append(t)
    t.start()

    for t in t_l:
    t.join()

    print(x) #最终结果就是0

    了解知识:死锁和解决死锁的方法(递归锁) 信号量

    死锁实例

    import time
    from threading import Thread, Lock

    mutexA = Lock()
    mutexB = Lock()

    class Mythread(Thread):
    def run(self):
    self.f1()
    self.f2()

    def f1(self):
    mutexA.acquire()
    print('%s 拿到A锁' % self.name) #self.name是线程名
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    mutexB.release()
    mutexA.release()

    def f2(self):
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    time.sleep(1)
    mutexA.acquire()
    print('%s 拿到了A锁' % self.name)
    mutexA.release()
    mutexB.release()

    if __name__ == '__main__':
    for i in range(10):
    t = Mythread()
    t.start()

    代码解读:

    开始执行函数,此时10个线程同时起来了,第一个线程在执行run,run里面执行两个函数f1和f2,线程1拿到了A锁,线程1又拿到了B锁,此时程序再往下走线程1释放了A锁和B锁,紧接着执行f2函数,此时线程1拿到了B锁,然后睡了1秒的同时,线程2起来了,线程2执行f1,此时线程2拿到了A锁,线程2想要拿B锁,由于线程是异步的,所以此时B锁在线程1的f2里睡着(1秒),此时线程1一秒过后想要拿A锁,但是这时候A锁在线程2里面等着释放(线程2还在执行f1,等着拿到B锁再执行释放A,B锁)所以这时候线程1在执行f2代码的时候由于A锁再线程2手里,得不到A锁代码就走不下去(无法执行后面的释放代码),线程2想要拿B锁,由于B锁在线程1手里(无法执行后面的释放代码),所以就形成了死锁递归锁,程序执行不下去

    解决死锁的办法(使用RLock递归锁)

    import time
    from threading import Thread, RLock #使用递归锁要倒入RLock模块

    obj = RLock() #实例化一个变量等于RLock
    mutexA = obj #obj赋值给变量
    mutexB = obj

    class Mythread(Thread):
    def run(self):
    self.f1()
    self.f2()

    def f1(self):
    mutexA.acquire()
    print('%s 拿到A锁' % self.name) #self.name是线程名
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    mutexB.release()
    mutexA.release()

    def f2(self):
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    time.sleep(1)
    mutexA.acquire()
    print('%s 拿到了A锁' % self.name)
    mutexA.release()
    mutexB.release()

    if __name__ == '__main__':
    for i in range(10):
    t = Mythread()
    t.start()

    PS:RLock递归锁的特点就是可以连续的acquire(上锁)不需要release(释放),而通常的Lock不能连续acquire(上锁),必须release(释放)后才能再次acquire(上锁)

    信号量实例

    信号量是控制同一时刻并发执行的任务数(和线程池、进程池很相似)

    from threading import Thread,Semaphore,current_thread
    import time,random

    sm = Semaphore(5) #括号内就是设置并发执行的任务数

    def task():
    with sm: # with 这个关键词就是把acquire和release合并成一步,自动执行,不需要写代码了
    print('%s 正在上厕所' %current_thread().name)
    time.sleep(random.randint(1,4))

    if __name__ == '__main__':
    for i in range(20):
    t = Thread(target=task)
    t.start()

    PS:可以看到第一次最多同时执行了5个线程,然后是有几个线程优先结束,然后执行几个线程

  • 相关阅读:
    POJ 2175 Evacuation Plan 费用流 负圈定理
    POJ 2983 Is the Information Reliable? 差分约束
    codeforces 420B Online Meeting
    POJ 3181 Dollar Dayz DP
    POJ Ant Counting DP
    POJ 1742 Coins DP 01背包
    中国儒学史
    产品思维30讲
    Java多线程编程核心技术
    编写高质量代码:改善Java程序的151个建议
  • 原文地址:https://www.cnblogs.com/shizhengquan/p/10270436.html
Copyright © 2011-2022 走看看