python多线程编程(3): 使用互斥锁同步线程

问题的提出

上一节的例子中,每个线程互相独立,相互之间没有任何关系。现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1。很容易写出这样的代码:

# encoding: UTF-8import threadingimport time

class MyThread(threading.Thread):    def run(self):        global num        time.sleep(1)        num = num+1        msg = self.name+' set num to '+str(num)        print msgnum = 0def test():    for i in range(5):        t = MyThread()        t.start()if __name__ == '__main__':    test()

但是运行结果是不正确的:

Thread-5 set num to 2
Thread-3 set num to 3
Thread-2 set num to 5
Thread-1 set num to 5
Thread-4 set num to 4

问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期。这种现象称为“线程不安全”。

互斥锁同步

上面的例子引出了多线程编程的最常见问题:数据共享。当多个线程都修改某一个共享数据的时候,需要进行同步控制。

线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

threading模块中定义了Lock类,可以方便的处理锁定:

#创建锁mutex = threading.Lock()#锁定mutex.acquire([timeout])#释放mutex.release()

其中,锁定方法acquire可以有一个超时时间的可选参数timeout。如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理。

使用互斥锁实现上面的例子的代码如下:

import threadingimport time

class MyThread(threading.Thread):    def run(self):        global num         time.sleep(1)

        if mutex.acquire(1):              num = num+1            msg = self.name+' set num to '+str(num)            print msg            mutex.release()num = 0mutex = threading.Lock()def test():    for i in range(5):        t = MyThread()        t.start()if __name__ == '__main__':    test()

运行结果:

Thread-3 set num to 1
Thread-4 set num to 2
Thread-5 set num to 3
Thread-2 set num to 4
Thread-1 set num to 5

可以看到,加入互斥锁后,运行结果与预期相符。

同步阻塞

当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“同步阻塞”(参见多线程的基本概念)。

直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

互斥锁最基本的内容就是这些,下一节将讨论可重入锁(RLock)和死锁问题。

多线程编程(3): 使用互斥锁同步线程相关推荐

  1. python多线程编程(2): 使用互斥锁同步线程

    上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的代码: # ...

  2. python 线程锁_python多线程编程(3): 使用互斥锁同步线程

    问题的提出 上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的 ...

  3. python多线程编程(3): 使用互斥锁同步线程

    问题的提出 上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的 ...

  4. python多线程同步与互斥_python多线程编程(3): 使用互斥锁同步线程

    问题的提出 上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的 ...

  5. Linux线程同步(二)---互斥锁实现线程同步

    一 why 先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 在博客&l ...

  6. Java并发编程实战之互斥锁

    文章目录 Java并发编程实战之互斥锁 如何解决原子性问题? 锁模型 Java synchronized 关键字 Java synchronized 关键字 只能解决原子性问题? 如何正确使用Java ...

  7. 互斥锁实现线程互斥(嵌入式学习)

    互斥锁实现线程互斥 互斥锁的概念 互斥锁的函数 示例代码 互斥锁的概念 互斥锁(Mutex)是一种用于多线程编程的同步原语(synchronization primitive),用于实现线程之间的互斥 ...

  8. 如何避免操作系统中多线程资源竞争的互斥与同步?

    作者 | 小林coding 来源 | 小林coding(ID:CodingLin) 前言 先来看看虚构的小故事 已经晚上 11 点了,程序员小明的双手还在键盘上飞舞着,眼神依然注视着的电脑屏幕. 没办 ...

  9. 多线程(二)互斥锁详解

    目录 一.什么是互斥锁 二.为什么需要互斥锁 三.互斥锁的原理 四.互斥锁的相关接口 五.互斥锁的使用举例 一.什么是互斥锁 保证线程安全的一种锁机制,在同一时刻,只允许一个执行流去访问临界资源. 二 ...

最新文章

  1. Django模板过滤器详解
  2. 检查IP是否可用的方法
  3. linux系统系统盘制作工具,轻松制作Linux系统启动盘的四种方法
  4. centos7安装php8,centos8安装php7.4
  5. powershell awk_谈谈 PowerShell
  6. Rokon 关于精灵的点击事件
  7. map--Bit Compression
  8. 自称世界上最权威监控软件FlexiSpy被黑删库,怎么做到的?
  9. 深思 JAVA IT 求职
  10. html5 星际摩托,HTML5 星际陨石环绕动效
  11. 给工具箱中的控件添加图标
  12. linux 刷新网络配置,3 Linux 网络配置
  13. 【问题记录】git报错:[remote rejected] (pre-receive hook declined)
  14. oracle 逗号连接表是相当于什么
  15. docker之网络管理
  16. SAS中的intnx函数
  17. 轻松解决 f2pool鱼池ethermine连接失败antpool矿池连接不上的问题E池连接超时
  18. p37 p38 p39 p40 p41
  19. 基于android的宠物领养系统
  20. 为什么我们从 Python 切换到 Go

热门文章

  1. dedecms文章页面URL路径优化
  2. 入住博客园,小庆一下
  3. android:configChanges属性
  4. CoreAnimation-CATransaction
  5. eas之Uuid和BOSUuid 区别
  6. windows下搭建SSH隧道内网映射
  7. FastDFS-单机版安装
  8. 用java实现邮件发送验证码
  9. 一些Layout的坑
  10. Enterprise Solution 进销存管理软件 C/S架构,支持64位系统 物流,资金流,信息流全面集成...