python锁学习笔记

"""
① 互斥锁:Lock,一次只能放行一个,可以通过 with 语句调用。

② 可重入锁:RLock,一次只能放行一个,可以通过 with 语句调用。

③ 条件锁:Condition,一次可以放行任意个,可以通过 with 语句调用。

④ 事件锁:Event,一次全部放行,不能通过 with 语句调用。

⑤ 信号量锁:semaphore,一次可以放行特定个,可以通过 with 语句调用。

Event是python中的事件锁,Event对象有一个信号标志,默认是False, 默认是阻塞的,需要使用Event.set()方法来设置为True,
可以将Event传入线程内,然后通过Event.wait()方法阻塞线程,实现线程同步,不过Event对象一次放行所有的进程;

Semaphore是python中的信号量锁,可以用来控制线程的并发数量;

"""
import threading
import time

DENG = {False: "红灯",
        True: "绿灯"}

class Event_LOCK(object):
    def __init__(self):
        pass
    def light(self, env):
        is_lock = env.is_set()
        print("当前时间是:{}, 红绿灯是:{}, 还有3S结束!".format(time.ctime(), DENG[is_lock]))
        time.sleep(3)
        if env.is_set:
            print("绿灯放行!")
            env.set()

    def car(self, env, name):
        print("当前时间是:{}, 车: {} 在等红灯!".format(time.ctime(), name))
        env.wait()
        print("当前时间是:{}, 车: {} 通过!".format(time.ctime(), name))


    def run(self):
        event = threading.Event()
        thread_light = threading.Thread(target=self.light, args=(event, ))
        thread_light.start()

        for each in "ABCDE":
            t1 = threading.Thread(target=self.car, args=(event, each))
            t1.start()
# Demo 红绿灯 for threading.Event()对象
"""
事件锁 Event 并没有实现魔法方法 enter() 和 exit(),
所以不能通过 with 语句调用

Event对象的函数:
# 生成一个事件锁对象
eve = threading.Event()

# 将事件锁设置为红灯状态
eve.clear()
 
# 判断事件锁的状态
eve.is_set()

# 将当前线程设置’等待‘状态
eve.wait()

# 将事件锁设置为绿灯状态
eve.set()
"""
#Event_LOCK().run()



# Demo 上厕所 for threading.Semaphore

class Semaphore_LOCK(object):
    def __init__(self):
        pass

    # Semaphore 里面也实现了 __enter__() 与 __exit__() 两个魔法方法,
    # 所以也是可以通过 with 语句调用的
    def deal(self, sem, name):
        sem.acquire()
        print("当前时间: {}, {}开始上厕所!".format(time.ctime(), name))
        time.sleep(5)
        sem.release()
        print("当前时间: {}, {}出来了!,厕所空了!\n".format(time.ctime(), name))

    def deal_use_with(self, sem, name):
        with sem:
            print("当前时间: {}, {}开始上厕所!".format(time.ctime(), name))
            time.sleep(4)
            print("当前时间: {}, {}出来了!,厕所空了!\n".format(time.ctime(), name))

    def run(self):
        # 只有四个坑,10个人上厕所,一次最多只能上4个人
        sem = threading.Semaphore(4) #noqa
        staffs = ["sam", 'jack', 'rose', 'dog', 'bey',
                  'tom', 'cat', 'black', 'shit', 'no']
        for people in staffs:
            #t1 = threading.Thread(target=self.deal, args=(sem, people))
            t1 = threading.Thread(target=self.deal_use_with, args=(sem, people))
            t1.start()
"""
Semaphore对象的函数:
# 生成一个信号量锁对象
sem = threading.Semaphore()

# 上锁,内置计数器减一
sem.acquire()

# 解锁,内置计数器加一
sem.release()
"""
#Semaphore_LOCK().run()


"""
Condition对象是python中的条件锁,内部使用LOCK和RLock锁实现,
所以具有阻塞的特性,再增加了暂停线程运行的功能,
可以用来实现同步复杂的线程间通信;

# 生成一个条件锁对象
cond = threading.Condition()

# 上锁
cond.acquire()

# 解锁
cond.release()

# 挂起线程,直到收到一个 notify 通知才会被唤醒
cond.wait()

# 唤醒一个 Condition 的 waiting 池中的线程
cond.notify()

# 唤醒所有 Condition 的 waiting 池中的线程
cond.notify_all()
"""



import threading
import time

condition = threading.Condition()
products = 0


class Producer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        global condition, products
        while True:
            if condition.acquire():
                if products < 10:
                    products += 1
                    print("Producer(%s):"
                          " deliver one, now products:%s" %
                          (self.name, products))
                    condition.notify()
                else:
                    print("Producer(%s):already 10,"
                          " stop deliver, now products:%s" %
                          (self.name, products))
                    condition.wait()
                condition.release()
                time.sleep(2)


class Consumer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        global condition, products
        while True:
            if condition.acquire():
                if products > 1:
                    products -= 1
                    print("Consumer(%s):consume one,"
                          " now products:%s" %
                          (self.name, products))
                    condition.notify()
                else:
                    print("Consumer(%s):only 1,"
                          " stop consume, products:%s" %
                          (self.name, products))
                    condition.wait()
                condition.release()
                time.sleep(2)


# if __name__ == "__main__":
#     for p in range(0, 5):
#         p = Producer()
#         p.start()
#
#     for c in range(0, 2):
#         c = Consumer()
#         c.start()

"""
互斥锁的使用:
互斥锁需要成对出现,否则会出现死锁的问题。

# 生成互斥锁对象
lock = threading.Lock()

# 获取锁,未获取到程序将会阻塞(当一个线程在执行被上锁的代码块时,将不允许切换到其他线程)
lock.acquire()

# 释放锁
lock.release()

# 判断该锁对象是否处于上锁状态
lock.locked()
"""



lock = threading.Lock()
NUM = 0
print("lock status: %s" % lock.locked())

import inspect

class LOCK_DEMO(object):
    def __init__(self, lock):
        self.lock = lock

    # 动态获取当前执行的函数名
    def get_current_function_name(self):
       return inspect.stack()[1][3]

    def add(self):
        lock.acquire()
        print("lock status: %s in %s" % (lock.locked(), self.get_current_function_name()))
        global NUM
        for i in range(1000000):
            NUM += 1
        print("lock status: %s in %s" % (lock.locked(), self.get_current_function_name()))
        lock.release()
        print("lock status: %s in %s" % (lock.locked(), self.get_current_function_name()))

    def add_with(self):
        global NUM
        with lock:
            # 自动加锁
            for i in range(1000000):
                NUM += 1
            # 自动解锁

    def delete(self):
        print("lock status: %s in %s" % (lock.locked(), self.get_current_function_name()))
        lock.acquire()
        print("lock status: %s in %s" % (lock.locked(), self.get_current_function_name()))
        global NUM
        for i in range(1000000):
            NUM -= 1
        print("lock status: %s in %s" % (lock.locked(), self.get_current_function_name()))
        lock.release()
        print("lock status: %s in %s" % (lock.locked(), self.get_current_function_name()))

    def run(self):
        t1 = threading.Thread(target=self.add_with)
        t2 = threading.Thread(target=self.delete)
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print("NUM is: %s" % NUM)

LOCK_DEMO(lock).run()


"""
死锁现象
一般来说,形成死锁有两种形式
① 一个线程里面嵌套获取一把互斥锁。
② 多个线程不按顺序同时获取多个锁,
例如:线程1嵌套获取ab两个锁,线程2嵌套获取ba两个锁,当线程1获取到了a在等待b,而线程2获取到了b在等待a,两个线程就形成了一个循环等待的圆,从而形成死锁。

对于第一种情况,可以使用可重入锁(RLOCK)。
对于第二情况,其实和 mysql 中的死锁性质差不多,因争夺资源而造成的一种死循环,保证多个线程获取锁的顺序是同样的即可避免这种情况,即获取锁和释放锁要成对出现。
"""
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值