Python中的锁
一、全局解释器锁(GIL)
1、什么是全局解释器锁
在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使用权消失后才能使用全局解释器(cpu),即时多个线程直接不会相互影响在同一个进程下也只有一个线程使用cpu,这样的机制称为全局解释器锁(GIL)。
2、全局解释器锁的好处
1、避免了大量的加锁解锁的好处
2、使数据更加安全,解决多线程间的数据完整性和状态同步
3、全局解释器的缺点
多核处理器退化成单核处理器,只能并发不能并行。
同一时刻的某个进程下的某个线程只能被一个cpu所处理,所以在GIL锁下的线程只能被并发,不能被并行。 实例:
import time
import threading def sub():
global num
num -= 1
time.sleep(1)
num = 100 # 定义一个全局变量
l = [] # 定义一个空列表,用来存放所有的列表
for i in range(100): # for循环100次
t = threading.Thread(target=sub) #每次循环开启一个线程
t.start() # 开启线程
l.append(t) # 将线程加入列表l
for i in l:
i.join() # 这里加上join保证所有的线程结束后才运行下面的代码
print(num)
# 输出结果为0
二、同步锁
1、什么是同步锁?
同一时刻的一个进程下的一个线程只能使用一个cpu,要确保这个线程下的程序在一段时间内被cpu执,那么就要用到同步锁。
2、为什么用同步锁?
因为有可能当一个线程在使用cpu时,该线程下的程序可能会遇到io操作,那么cpu就会切到别的线程上去,这样就有可能会影响到该程 序结果的完整性。
3、怎么使用同步锁?
只需要在对公共数据的操作前后加上上锁和释放锁的操作即可。
4、实例:
import time
import threading R = threading.Lock() def sub():
global num
R.acquire() # 加锁,保证同一时刻只有一个线程可以修改数据
num -= 1
R.release() # 修改完成就可以解锁
time.sleep(1) num = 100 # 定义一个全局变量
l = [] # 定义一个空列表,用来存放所有的列表
for i in range(100): # for循环100次
t = threading.Thread(target=sub) # 每次循环开启一个线程
t.start() # 开启线程
l.append(t) # 将线程加入列表l
for i in l:
i.join() # 这里加上join保证所有的线程结束后才运行下面的代码
print(num)
# 输出结果为0
5、扩展知识
1、GIL的作用:多线程情况下必须存在资源的竞争,GIL是为了保证在解释器级别的线程唯一使用共享资源(cpu)。
2、同步锁的作用:为了保证解释器级别下的自己编写的程序唯一使用共享资源产生了同步锁。
三、递归锁和死锁
1、什么是死锁?
指两个或两个以上的线程或进程在执行程序的过程中,因争夺资源而相互等待的一个现象
import time
import threading A = threading.Lock()
B = threading.Lock()
import threading class obj(threading.Thread):
def __init__(self):
super().__init__() def run(self):
self.a() # 如果两个锁同时被多个线程运行,就会出现死锁现象
self.b()
def a(self):
A.acquire()
print('')
B.acquire()
print(456)
time.sleep(1)
B.release()
print('qweqwe')
A.release()
def b(self):
B.acquire()
print('asdfaaa')
A.acquire()
print('(⊙o⊙)哦(⊙v⊙)嗯')
A.release()
B.release()
for i in range(2): # 循环两次,运行四个线程,第一个线程成功处理完数据,第二个和第三个就会出现死锁
t = obj()
t.start()
程序会出现阻塞现象
2、什么是递归锁?
在Python中为了支持同一个线程中多次请求同一资源,Python提供了可重入锁。这个RLock内部维护着一个Lock和一个counter
变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获
得资源。
import time
import threading A = threading.RLock() # 这里设置锁为递归锁
import threading class obj(threading.Thread):
def __init__(self):
super().__init__() def run(self):
self.a()
self.b() def a(self): # 递归锁,就是将多个锁的钥匙放到一起,要拿就全拿,要么一个都拿不到
# 以实现锁
A.acquire()
print('')
print(456)
time.sleep(1)
print('qweqwe')
A.release()
def b(self):
A.acquire()
print('asdfaaa')
print('(⊙o⊙)哦(⊙v⊙)嗯')
A.release()
for i in range(2):
t = obj()
t.start()
四、信号量(semaphore)
1、什么是信号量?
同进程的一样,semaphore管理一个内置的计数器,每当调用acquire()时内置函数-1,每当调用release()时内置函数+1。
计数器不能为0,当计数器为0时acquire()将阻塞线程,直到其他线程调用release()。
import threading
import time mysf = threading.Semaphore(5) # 创建信号量对象,(5表示这个锁同时支持的个数) def func():
if mysf.acquire(): # 因为使用了信号量,下面的输出就会5个5个的同时输出
print(threading.currentThread().getName() + 'get semaphore')
time.sleep(1)
mysf.release()
for i in range(20):
t = threading.Thread(target=func)
t.start()
Python中的锁的更多相关文章
- 并发编程---线程 ;python中各种锁
一,概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 --车间负责把资源整合到 ...
- python中的锁lock=threading.Lock()
避免多个线程保卫同一块数据的时候,产生错误,所以加锁来防止这种问题 个人理解:当打印结果是交替打印时,但是如果需求是需要打印完一个线程的内容后,再去打印另一个线程的内容,就需要用到锁 不加锁打印结果: ...
- Python并发编程之谈谈线程中的“锁机制”(三)
大家好,并发编程 进入第三篇. 今天我们来讲讲,线程里的锁机制. 本文目录 何为Lock( 锁 )?如何使用Lock( 锁 )?为何要使用锁?可重入锁(RLock)防止死锁的加锁机制饱受争议的GIL( ...
- python中的各种锁
一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...
- python基础24 -----python中的各种锁
一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...
- python学习笔记——多进程中的锁Lock
1 进程锁 python编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性. 每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一线程访问对象. 在python中我 ...
- Python 中的进程与 锁
理论知识 操作系统背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操 ...
- 操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁
并发编程前言: 1.网络应用 1)爬虫 直接应用并发编程: 2)网络框架 django flask tornado 源码-并发编程 3)socketserver 源码-并发编程 2.运维领域 1)自动 ...
- Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)
1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...
随机推荐
- vue-cli3.0 项目如何使用sass
执行: npm install node-sass --save-dev npm install sass-loader --save-dev 自动安装sass,vue-cli3.0 不需要在 web ...
- AngularJS初识
AngularJS 简介 AngularJS是一个javaScript框架,是一个用JavaScript编写的库,通过指令扩展了HTML,且通过表达式绑定数据到HTML中. AngularJS使开发 ...
- sublime自动保存设置
首选项——用户设置 (Preferences:Settings - User) 行末添加"save_on_focus_lost": true 注意用逗号分隔 保存即可 save_o ...
- 在js中插入html语句
连上数据库之后,填充数据时往往需要在js中插入html语句 做法是: <body> <div class="modal-body" id="delete ...
- HTML常用基础标签
HTML常用基础标签 带有语义的标签 <em> </em> 强调 <strong> </strong> 比em强调级别高 <abbr> &l ...
- MyCat-简介
一MyCat简介 java编写的数据库中间件 Mycat运行环境需要JDK. Mycat是中间件.运行在代码应用和MySQL数据库之间的应用. 前身 : corba. 是阿里开发的数据库中间件.实现M ...
- 【java】-- 多线程快速入门
1.什么是进程?什么是线程?两者区别? 1.每个正在系统上运行的程序都是一个进程,每个进程包含一到多个线程,多线程处理就是允许一个进程中在同一时刻执行多个任务. 2.线程是一组指令的集合,或者是程序的 ...
- webpack的devServer配置错误
首先声明,之前vue项目没有报错,做react项目这样配置就报错了. 一.问题描述 [HMR] Hot Module Replacement is disabled. 二.问题分析 不太理解控制台为什 ...
- 一道简单的dp题 --- Greenhouse Effect CodeForces - 269B
题目链接: https://vjudge.net/problem/36696/origin 题目大意: 要求从1到m升序排列,点可以随意移动,问最少需要移动多少次, 思路: 动态规划 可以推出转移方程 ...
- pymongo使用手册
MongoDB是由C++语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似JSON对象,它的字段值可以包含其他文档.数组及文档数组,非常灵活.在这一节中,我们就来看 ...