写过多线程程序的人确定对各类锁很熟悉,尤为是下面这种代码python
def lock_usage: lock.Lock() if(...) : lock.Unlock() return lock.Unlock() return
了避免形成死锁,须要在每一个return语句以前都释放锁。像上面的代码中,若是代码的执行路径不少,代码中就会包含大量的unlock语句,代码混乱仍是小事儿,若是万一忘掉了unlock,就是个潜在的危险。除了锁以外,包括文件描述符的关闭等涉及到资源释放的操做都会有这种问题。
为了解决内存泄漏的内存问题,现代的编程语言提供了垃圾回收机制。一样为了解决上面这种有限资源的释放问题,不少语言都提供了一些语法特性。Python有with语句,C#有using,Go有defer。 先看解决这种问题的常规作法,使用finally编程
try: lock.Lock() ...... except: prcess_except() finally: lock.Unlock
这么写使得代码很乱,尤为是当......处的代码也包含有相似代码时,会使得代码更加混乱。再来看使用with语句后的代码多线程
class LockContext(object): __init__(self, lock): self.lock = lock __enter__(self): self.Lock() __exit__(self, type, value, traceback): if type != None: process_except() self.Unlock() return false with LockContext(lock) as lock: .......
这样写出来,代码量虽然差很少,可是结构清晰了不少。在上面的代码中__init__中的赋值是可选的,只要保证可以访问到所需的变量就可。Python中的with语句中要求对象实现__enter__和__exit__函数。调用with语句时,会先分析该语句,执行__enter__函数,而后在当前suite退出时,会调用__exit__函数。__exit__函数中除了能够作释放资源的操做以外,同时也是异常处理的地方。若是当前suite正常退出,没有抛出任何异常,__exit__的几个参数均为None。不然,则将此异常的type、value、traceback做为参数传递给__exit__函数,同时,若是__exit__返回false,此异常会再次抛出,上一级代码suite能够继续处理,若是__exit__返回true,那么此异常就不会被再次抛出了编程语言