一、数据共享
  多个线程内部有自己的数据栈,数据不共享;全局变量在多个线程之间是共享的。

 1 # 线程数据共享不安全加锁
 2
 3 import time
 4 from threading import Thread, Lock
 5
 6
 7 num = 100
 8
 9 def func(t_lock):
10     global num
11     t_lock.acquire()
12     mid = num
13     mid -= 1
14     time.sleep(0.01) # 设置一个时间,模拟数据修改时,先从内存中拿出作修改,在把结果放回去的时间差
15     num = mid
16     t_lock.release()
17
18 if __name__ == '__main__':
19
20     t_lock = Lock()
21
22     t_lst = []
23     for i in range(10):
24         t_thread = Thread(target=func, args=(t_lock,))
25         t_lst.append(t_thread)
26         t_thread.start()
27     [t_obj.join() for t_obj in t_lst]    #必须加join,因为主线程和子线程不一定谁快,一般都是主线程快一些,所有我们要等子线程执行完毕才能看出效果
28
29     print('主线程结束!', num)    # 结果为90

数据共享实例

二、同步锁(互斥锁) - 产生死锁
  进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额,进程的死锁和线程的是一样的,而且一般情况下进程之间是数据不共享的,不需要加锁,由于线程是对全局的数据共享的,所以对于全局的数据进行操作的时候,要加锁。
  死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁

 1 from threading import Thread,Lock
 2 import time
 3
 4 class MyThread(Thread):
 5     def run(self):
 6         self.func1()
 7         self.func2()
 8     def func1(self):
 9         mutexA.acquire()
10         print('\033[41m%s 拿到A锁>>>\033[0m' %self.name)
11         mutexB.acquire()
12         print('\033[42m%s 拿到B锁>>>\033[0m' %self.name)
13         mutexB.release()
14         mutexA.release()
15
16     def func2(self):
17         mutexB.acquire()
18         print('\033[43m%s 拿到B锁???\033[0m' %self.name)
19         time.sleep(2)
20 #分析:当线程1执行完func1,然后执行到这里的时候,拿到了B锁,线程2执行func1的时候拿到了A锁,那么线程2还要继续执行func1里面的代码,再去拿B锁的时候,发现B锁被人拿了,那么就一直等着别人把B锁释放,那么就一直等着,等到线程1的sleep时间用完之后,线程1继续执行func2,需要拿A锁了,但是A锁被线程2拿着呢,还没有释放,因为他在等着B锁被释放,那么这俩人就尴尬了,你拿着我的老A,我拿着你的B,这就尴尬了,俩人就停在了原地
21
22         mutexA.acquire()
23         print('\033[44m%s 拿到A锁???\033[0m' %self.name)
24         mutexA.release()
25         mutexB.release()
26
27 if __name__ == '__main__':
28
29     mutexA=Lock()    # 同步锁必须这样创建
30     mutexB=Lock()
31     for i in range(10):
32         t=MyThread()
33         t.start()
34
35 '''
36 Thread-1 拿到A锁>>>
37 Thread-1 拿到B锁>>>
38 Thread-1 拿到B锁???
39 Thread-2 拿到A锁>>>
40 然后就卡住,死锁了
41 '''

死锁现象

三、解决死锁方案 - 递归锁
  解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。
  这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:

 1 import time
 2 from threading import Thread,RLock
 3
 4
 5 class MyThread(Thread):
 6
 7     def __init__(self, lockA, lockB):
 8         super().__init__()
 9         self.lockA = lockA
10         self.lockB = lockB
11     def run(self):
12         self.func1()
13         self.func2()
14
15     def func1(self):
16         self.lockA.acquire()
17         print('我是func1')
18         self.lockB.acquire()
19         print('func1中有其他事')
20         self.lockB.release()
21         self.lockA.release()
22
23     def func2(self):
24         self.lockB.acquire()
25         print('我是func2')
26         time.sleep(0.5)
27         self.lockA.acquire()
28         print('func2中有什么事')
29         self.lockA.release()
30         self.lockB.release()
31
32 if __name__ == '__main__':
33
34     lockA = lockB = RLock()
35
36     t1 = MyThread(lockA, lockB)
37     t1.start()
38     t2 = MyThread(lockA, lockB)
39     t2.start()
40     print('嗯嗯,两人不错')

递归锁

转载于:https://www.cnblogs.com/hq82/p/9858375.html

48_并发编程-线程-资源共享/锁相关推荐

  1. python 线程同步_Python并发编程-线程同步(线程安全)

    Python并发编程-线程同步(线程安全) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 线程同步,线程间协调,通过某种技术,让一个线程访问某些数据时,其它线程不能访问这些数据,直 ...

  2. 高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析

    文章目录 概述 jstack或者可视化工具检测是否死锁(没有) 原因分析 概述 高并发编程-线程通信_使用wait和notify进行线程间的通信 - 遗留问题 我们看到了 应用卡住了 .... 怀疑是 ...

  3. 并发编程——线程协作

    并发编程--线程协作 ​ 前面学习了线程,那么并发编程中,如何协调多个线程来开发呢? Semaphore ​ 信号量跟前面将的同步互斥解决方案--信号量是一个东西,这是JDK的信号量实现. 源码分析 ...

  4. 并发编程中的锁、条件变量和信号量

    在并发编程中,经常会涉及到锁.条件变量和信号量.本文从并发开始,探究为什么需要它们,它们的概念,实现原理以及应用. 并发简介 并发是指多个事情,在同一时间段内同时发生了.和并发经常一起被提到的是并行. ...

  5. Java 并发编程 -- 线程池源码实战

    一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...

  6. 判断线程是否执行完毕_Java并发编程 | 线程核心机制,基础概念扩展

    源码地址:GitHub || GitEE 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效率.下面提供一个 ...

  7. 并发编程——线程——锁

    并发编程中避免不了在同一时间对同一数据的更改,因此,对锁的使用变得尤为重要,什么时间.什么场景该用什么类型的锁都是有讲究的,接下来介绍几种常见的锁. 死锁现象 问题产生需求,在学新的锁之前先来看看我们 ...

  8. Java并发编程,无锁CAS与Unsafe类及其并发包Atomic

    为什么80%的码农都做不了架构师?>>>    我们曾经详谈过有锁并发的典型代表synchronized关键字,通过该关键字可以控制并发执行过程中有且只有一个线程可以访问共享资源,其 ...

  9. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型...

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

最新文章

  1. 二次元会让人脸识别失效吗?
  2. S3C2440 WINCE6将USB DEVICE改成USB HOST,实现两个USB HOST
  3. 三十而已,工程师如何做好职业成长?
  4. Python项目生成requirements.txt的多种方式
  5. tyvj1194 划分大理石
  6. ROS Kinetic 安装指南
  7. Aplication的意义和生命周期,与Context的关系,以及关于Aplication和Context相关问题的记录和解决办法...
  8. linux添加计划任务(转载)
  9. 转载--认识迅雷界面引擎
  10. 企业综合安防管理平台
  11. 我的第一本社会心理学(part1)--社会心理学是研究个体和群体的社会心理、社会行为及其发展规律的科学
  12. 采用腾讯云直播断流续播相关问题
  13. 简明c语言,简明易懂的C语言俄罗斯方块
  14. 尤雨溪:Vue Function-based API RFC
  15. 又是一年叶落时(二)
  16. DOM 树是如何构建的 ?
  17. php学到最后,【A0365】[PHP视频教程]新开班布尔教育最后一期PHP 入门到实战视频教程 百度云 网盘...
  18. 厄米多项式(Hermite Polynomials)
  19. [蓝桥杯][2013年第四届真题]带分数(DFS,next_permutation两种方法)
  20. docker 基础工作原理(一)

热门文章

  1. oracle扩容日志文件,调整Oracle Redo Logfile日志文件的大小
  2. 增效工具_【危中寻机】降本增效生存之道 运用IE基础工具提升制造效率
  3. 【牛客 - 21302】被3整除的子序列(线性dp)
  4. 【CodeForces - 227B 】Effective Approach (STL,思维)
  5. 原生JS动态计算输入框文本内容的宽度,当内容宽度超过输入框的宽度时可控
  6. php移动端url,什么是PC和移动端URL路径规范化
  7. mysql win10 优化设置_windows10如何优化?系统优化设置方法
  8. 把网卡指定给vm虚拟机_为VMWare虚拟网卡指定静态的MAC地址
  9. Java单例模式的几种实现方式
  10. 京东华为 Java开发历年经典题汇总