一、线程锁(互斥锁)

在一个程序内,主进程可以启动很多个线程,这些线程都可以访问主进程的内存空间,在Python中虽然有了GIL,同一时间只有一个线程在运行,可是这些线程的调度都归系统,操作系统有自身的调度规则,所以就可能造成,

  • 假设两个线程都在访问 global count= 0, 每个进程都会执行 count +=1 。(1)(2)(3)第一个线程申请GIL然后,读取global count到及进程到 cpu ,(4)然后cpu执行到一半,(5)把这个线程停了,将上下文保存到自身寄存器中。注意这时候没返回结果。这时候解释器就会把GIL释放,
  • (6)(7)(8)第二个线程申请GIL执行如上步骤,读取count= 0 ,cpu计算结束后将结果count=1 返回,(10)(11)解释器拿到结果进行赋值,此时count=1,这个进程运行结束,(12)(13)然后cpu从寄存器中第一个线程的执行状态,继续执行,注意这个读取的是寄存器中的上下文,就是第一次执行时 count= 0,及第一个线程的上下文。计算结果返回count =1 返回。就造成了结果的错误。

1.1 python中的线程锁(互斥锁mutex)

使用threading模块中的Lock类,得到一个全局锁实例。然后 Lock()实例下 有一个 acquire 方法为加锁, release 方法释放锁

import threading

count = 0
lock = threading.Lock() #申请一个锁 def count_():
global count #声明为全局变量
lock.acquire() #加锁,锁释放前不予许其他程序执行
count += 1
lock.release() #执行完 ,释放锁 thread_list = []
for i in range(10):
t = threading.Thread(target= count_)
t.start()
thread_list.append(t) for t in thread_list:
t.join() #主程序等待所有程序执行完毕 print('Count:{: ^4}'.format(count))
1.2 递归锁

基本用不上,主要目的就是防止锁里面加锁,然后程序无法解锁退出。

import threading,time

def run1():
print("grab the first part data")
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2) if __name__ == '__main__': num,num2 = 0,0
lock = threading.RLock()
for i in range(10):
t = threading.Thread(target=run3)
t.start() while threading.active_count() != 1:
print(threading.active_count())
else:
print('----all threads done---')
print(num,num2)

线程锁(互斥锁Mutex)及递归锁的更多相关文章

  1. 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  2. (转)经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  3. 多线程面试题系列(7):经典线程同步 互斥量Mutex

    前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...

  4. 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    本文转载于:http://blog.csdn.net/morewindows/article/details/7470936 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用 ...

  5. 转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  6. python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)

    9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕​详细解释:1.主 ...

  7. JoinableQueue队列,线程,线程于进程的关系,使用线程,线程的特点,守护线程,线程的互斥锁,死锁问题,递归锁,信号量

    1.JoinableQueue队列 JoinableQueue([maxsize]):这就像是一个Queue对象,但是队列允许项目的使用者通知生成者项目已经被成功处理.通知进程是使用共享的信号和条件变 ...

  8. 线程全局修改、死锁、递归锁、信号量、GIL以及多进程和多线程的比较

    线程全局修改 x = 100 def func1(): global x print(x) changex() print(x) def changex(): global x x = 50 func ...

  9. 并发编程(五)——GIL全局解释器锁、死锁现象与递归锁、信号量、Event事件、线程queue

    GIL.死锁现象与递归锁.信号量.Event事件.线程queue 一.GIL全局解释器锁 1.什么是全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多 ...

随机推荐

  1. c/c++ allocator 使用

    allocator 使用 作用:只开辟空间,不调用构造函数 操作一览表 allocator<T> a 定义一个名为a的allocator对象,它可以为类型为T的对象分配内存 a.alloc ...

  2. JAVA的三个版本EE,SE,ME

    1998年 SUN发布三个不同版本JAVA,分别是: Java J2EE(Java Platform,Enterprise Edition) JAVA企业版,应用为开发和部署可移植.健壮.可伸缩且安全 ...

  3. cURL模拟POST提交数据

    首先,是这个代码: <?php //curl模拟post提交数据$url = "http://127.0.0.1/immoc/output.php";$post_data = ...

  4. Windows和Linux之间 rsync数据同步

    转载于   https://www.linuxidc.com/Linux/2014-01/95722p2.htm rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——rem ...

  5. Java程序导出成.jar文件、生成.exe可执行文件及打包成可执行安装程序(可在无Java环境的计算机上运行)--以个人所得税计算器为例

    Java程序导出成.jar文件.生成.exe可执行文件及打包成可执行安装程序 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 需要准备的软件: jdk, ...

  6. java操作elasticsearch实现前缀查询、wildcard、fuzzy模糊查询、ids查询

    1.前缀查询(prefix) //prefix前缀查询 @Test public void test15() throws UnknownHostException { //1.指定es集群 clus ...

  7. [WeChall] Training: Encodings I (Training, Encoding)

    Training: Encodings I (Training, Encoding) We intercepted this message from one challenger to anothe ...

  8. 在Linux上编译Hadoop-2.4.0实践与总结

    问题导读: 1.编译源码前需要安装哪些软件? 2.安装之后该如何设置环境变量? 3.为什么不要使用JDK1.8? 4.mvn package -Pdist -DskipTests -Dtar的作用是什 ...

  9. node基础—函数的调用

    普通本地函数的调用 var http = require('http'); http.createServer(function(request,response){ response.writeHe ...

  10. MySQL高级知识(十五)——主从复制

    前言:本章主要讲解MySQL主从复制的操作步骤.由于环境限制,主机使用Windows环境,从机使用用Linux环境.另外MySQL的版本最好一致,笔者采用的MySQL5.7.22版本,具体安装过程请查 ...