linuxsir首页 LinuxSir.Org | Linux、BSD、Solaris、Unix | 开源传万世,因有我参与欢迎您!
网站首页 | 设为首页 | 加入收藏
您所在的位置:主页 > Linux基础建设 >

Python高级编程 - 锁的语法

时间:2019-09-18  来源:未知  作者:admin666

在使用用的过程中需要导入threading模块的Lock类

使用锁:

  • 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
  • 线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互 斥锁。
  • 互斥锁为资源引入一个状态:锁定/非锁定。

锁的语法

创建锁、锁定锁、释放锁

from threading import Lock

# 创建锁
mutex = Lock()
# 获取锁(上锁)
mutex.acquire()
# 释放锁(解锁)
mutex.release()

  在锁定锁的过程中acquire()方法可以接受一个blocking参数,

    如果设定blocking为True,则当前线程会堵塞,直到获取到这个锁为止(如果没有 指定,那么默认为True)

    如果设定blocking为False,则当前线程不会堵塞

 

  上锁和解锁的过程(假设是多线程调度):

    这个锁一般是为共享资源服务的,即多个线程同时使用共享资源。这个锁同一时间只能有一个线程调度,其他线程阻塞,只有当前调度的线程释放这个锁,阻塞的线程才能调度。

  锁的优点:

    确保了某段关键代码只能有一个线程从头到尾完整的执行。

  锁的缺点:

    组织了多线程的并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大的降低了;代码中可能存在多个锁,如果多个线程拥有多个锁,容易造成死锁。

  死锁的现象(实例):

 

# 死锁 两者都没有释放对方需要的锁,而释放的条件恰好是获取对方释放所需要的锁
# 线程1
class MyThread1(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        # 线程1获取A锁
        if mutexA.acquire():
            print(self.name+"-----do1---up-----")
            sleep(1)
            # 此时线程2获取了B锁,需要等待线程2释放B锁
            if mutexB.acquire():
                print(self.name + "-----do1---down-----")
                mutexB.release()
            mutexA.release()

# 线程2
class MyThread2(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        # 线程2获取B锁
        if mutexB.acquire():
            print(self.name + "-----do2---up-----")
            sleep(1)
            # 此时线程1获取了A锁,需要等待线程1释放A锁
            if mutexA.acquire():
                print(self.name + "-----do2---down-----")
                mutexA.release()
            mutexB.release()


mutexA = threading.Lock()
mutexB = threading.Lock()


if __name__ == '__main__':
    # 线程1和线程2同时执行
    t1 = MyThread1()
    t2 = MyThread2()
    t1.start()
    t2.start()   

 

  避免死锁的方法:银行家算法

多进程与多线程比较及选择

 是否采用多任务处理,取决于我们的任务类型

 如果是计算密集型,需要大量的CPU资源进行运算,代码的运行效率至关重 要,这样的任务一般不使用多线程进行,因为频繁的任务调度会拖慢CPU的
运算。

 如果是IO密集型,涉及到硬盘读写,网络读写等的任务,更多的时间在等待 IO操作完成,这一类任务可以放到多线程或多进程中来进行。

单线程、多线程、多进程(一起实现同一代码的时间)

 

# 单线程、多线程、多进程的使用及不同
# 简单的求和
def fib(x):
    res = 0
    for i in range(100000000):
        res += i*x
    return res


# 阶乘
def fac(x):
    if x < 2:
        return 1
    return x*fac(x-1)


# 简单的求和
def sum(x):
    res = 0
    for i in range(50000000):
        res += i*x
    return res


# 函数列表
funcs = [fib, fac, sum]
n = 100


class MyThread(threading.Thread):
    def __init__(self, func, args, name=""):
        super().__init__()
        self.name = name
        self.func = func
        self.args = args
        self.res = 0

    def getResult(self):
        return self.res

    def run(self):
        print("starting ", self.name, " at: ", ctime())
        self.res = self.func(self.args)
        print(self.name, "finished at: ", ctime())


def main():
    nfuncs = range(len(funcs))

    print("单线程".center(30, "*"))
    start = time()
    for i in nfuncs:
        print("start {} at: {}".format(funcs[i].__name__, ctime()))
        start_task = time()
        print(funcs[i](n))
        end_task = time()
        print("任务 耗时:", end_task-start_task)
        print("{} finished at: {}".format(funcs[i].__name__, ctime()))

    end = time()
    print("单线程运行时间:", end-start)
    print("单线程结束:".center(30, "*"))

    print()
    print("多线程".center(30, "*"))
    start = time()
    threads = []
    for i in nfuncs:
        # 一个线程绑定一个函数
        t = MyThread(funcs[i], n, funcs[i].__name__)
        threads.append(t)

    for i in nfuncs:
        # 同时启动线程
        threads[i].start()

    for i in nfuncs:
        threads[i].join()
        print(threads[i].getResult())
    end = time()
    print("多线程运行时间:", end-start)
    print("多线程结束:".center(30, "*"))

    print()
    print("多进程".center(30, "*"))
    start = time()
    process_list = []
    for i in nfuncs:
        # 一个进程绑定一个函数
        t = Process(target=funcs[i], args=(n, ))
        process_list.append(t)

    for i in nfuncs:
        # 同时启动进程
        process_list[i].start()

    for i in nfuncs:
        process_list[i].join()
    end = time()
    print("多进程运行时间:", end - start)
    print("多进程结束:".center(30, "*"))


if __name__ == "__main__":
    main()

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

友情链接
  • Mozilla发布Firefox 67.0.4,修复沙箱逃逸漏洞
  • 蚂蚁金服正式成为CNCF云原生计算基金会黄金会员
  • Firefox 68将采用Microsoft BITS安装更新
  • OpenSSH增加对存储在RAM中的私钥的保护
  • 谷歌想实现自己的curl,为什么?
  • Raspberry Pi 4发布:更快的CPU、更大的内存
  • Firefox的UA将移除CPU架构信息
  • Ubuntu放弃支持32位应用程序实属乌龙,Steam会否重回Ubuntu怀抱
  • Qt 5.13稳定版发布:引入glTF 2.0、改进Wayland以及支持Lottie动
  • 红帽企业Linux 7现已内置Redis 5最新版
  • Slack进入微软内部禁用服务清单,GitHub也在其列?
  • 安全的全新编程语言V发布首个可用版本
  • Windows Terminal已上架,快尝鲜
  • 阿里巴巴微服务开源生态报告No.1
  • 面世两年,Google地球将支持所有基于Chromium的浏览器
  • 推进企业容器化持续创新,Rancher ECIC千人盛典完美收官
  • CentOS 8.0最新构建状态公布,或于数周后发布
  • Debian移植RISC
  • 微软拆分操作系统的计划初现雏形
  • Oracle发布基于VS Code的开发者工具,轻松使用Oracle数据库
  • Ubuntu 19.10停止支持32位的x86架构
  • 微软为Windows Terminal推出全新logo
  • 联想ThinkPad P系列笔记本预装Ubuntu系统
  • 微软发布适用于Win7/8的Microsoft Edge预览版
  • 启智平台发布联邦学习开源数据协作项目OpenI纵横
  • 经过六个多月的延迟,微软终于推出Hyper
  • ZFS On Linux 0.8.1 发布,Python可移植性工作
  • DragonFly BSD 5.6.0 发布,HAMMER2状态良好
  • Linux Kernel 5.2
  • CentOS 8.0 看起来还需要几周的时间
  • 百度网盘Linux版正式发布
  • PCIe 6.0宣布:带宽翻倍 狂飙至256GB/s
  • PHP 7.4 Alpha 发布,FFI扩展,预加载Opcache以获得更好的性能
  • Canonical将在未来的Ubuntu版本中放弃对32位架构的支持
  • Scala 2.13 发布,改进的编译器性能
  • 微软的GitHub收购了Pull Panda,并且使所有订阅完全免费
  • Windows Subsystem for Linux 2 (WSL 2)现在适用于Windows 10用
  • Debian 10 “Buster”的RISC
  • MariaDB宣布发布MariaDB Enterprise Server 10.4
  • DXVK 1.2.2 发布,带来微小的CPU开销优化
  • DragonFlyBSD 5.6 RC1 发布,VM优化,默认为HAMMER2
  • PrimeNG 8.0.0 发布,支持Angular 8,FocusTrap等
  • GIMP 2.10.12 发布,一些有用的改进
  • 清华大学Anaconda 镜像服务即将恢复
  • Debian GNU/Linux 10 “Buster” 操作系统将于2019年7月6日发布
  • 时时彩论坛
  • 五星体育斯诺克
  • 北单比分直播
  • 河北11选5走势图
  • 福建体彩36选7开奖结果
  • 九龙图库下载