线程 Thread类 GIL锁 信号量 Event事件
线程的开启方法
进程是操作系统调度的最小单位,一个进程最少有一个主线程,而一个进程中可以开启多个线程
from threading import Thread
def task():
print('A child thread')
if __name__ == '__main__': # 这里是可以不用写的,但是规范起见还是写了
t = Thread(target=task)
t.start()
print('==>main thread')
GIL锁
"""
1. Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行
2. Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。
1、GIL锁它是在python解释器中的, 只在cpython中有, pypy解释器是没有GIL锁的,
2、起一个垃圾回收线程, 一个是正常执行的线程
3、设置了一把锁(GIL锁), 一个线程要想执行,必须拿到这把锁
4、同一时刻,开启一个进程,一个进程中可以有多个线程, 只能有一个线程在执行
5、如果是计算密集型:要开进程
6、如果是io密集型:要开线程
"""
进程与线程的比较

线程与进程的区别可以归纳为以下4点:
- 地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
- 通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
- 调度和切换:线程上下文切换比进程上下文切换要快得多。
- 在多线程操作系统中,进程不是一个可执行的实体。
进程消耗的资源比线程要大的多,相对的,调用起来也比线程要慢
# 进程调用时间演示
import time
from multiprocessing import Process
def task():
time.sleep(1)
print('A child process')
if __name__ == '__main__':
start = time.time()
p = Process(target=task)
p.start()
p.join()
print('master process')
print(time.time() - start)
# 输出结果
# A child process
# master process
# 1.069324016571045
# 线程调用时间演示
import time
from threading import Thread
def task():
time.sleep(1)
print('A child thread')
if __name__ == '__main__':
start = time.time()
t = Thread(target=task)
t.start()
t.join()
print('==>main thread')
print(time.time()-start)
# 输出结果
# A child thread
# ==>main thread
# 1.005803108215332
线程间的数据是共享的
def task():
global n
n=0
if __name__ == '__main__':
n=1
t=Thread(target=task)
t.start()
t.join()
print('主',n) # 查看结果为0,因为同一进程内的线程之间共享进程内的数据
Thread类的方法
t.is_alive() # 返回线程是否活动
t.getName() # 获取线程名
t.setName() # 更新线程名
threading.currentThread() # 返回当前的线程变量
threading.enumerate() # 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程
threading.activeCount() # 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
守护线程
from threading import Thread
import time
def task():
time.sleep(1)
print("我是子线程")
if __name__ == '__main__':
t = Thread(target=task,)
t.setDaemon(True) # 开启守护线程, 主线程结束,子线程跟着结束
t.start()
print("主线程")
线程互斥锁
from threading import Thread,Lock
import time
import random
def task(lock):
#上锁
lock.acquire()
global n
# 10个线程同时涌入导致数据不安全
time.sleep(random.random())
n -= 1
# 释放锁
lock.release()
if __name__ == '__main__':
start = time.time()
lock = Lock()
n = 100
l = []
for i in range(10):
t = Thread(target=task,args=(lock,))
t.start()
l.append(t)
for j in l:
j.join()
print('运算完毕:n = %s' %n)
print(time.time()-start)
信号量
from threading import Thread,Semaphore
import time
def task(i, sm):
# 上锁
sm.acquire()
print("%s:这个人开始上厕所了" % i)
time.sleep(3)
print("%s:这个人上完了" % i)
# 释放锁
sm.release()
# Semaphore:信号量可以理解为多把锁,同时允许多个线程来更改数据
if __name__ == '__main__':
sm = Semaphore(2) #
for i in range(10):
t = Thread(target=task, args=(i, sm))
t.start()
Event事件
from threading import Thread, Event
import time
def girl(event):
print("都女士正在恋爱中...")
time.sleep(3)
print("都女生分手了")
# 发出分手的信号
event.set()
def boy(i, event):
print("渣男:%s正在等待都女生分手" % i)
# 卡住
event.wait()
print("渣男:%s开始追了" % i)
if __name__ == '__main__':
event = Event()
t = Thread(target=girl, args=(event,))
t.start()
for i in range(10):
b_t = Thread(target=boy, args=(i, event))
b_t.start()
释放出信号,而读数据课以收信号,一旦示范出可以读的信号该线程才会运行
线程 Thread类 GIL锁 信号量 Event事件的更多相关文章
- 并发编程---死锁||递归锁---信号量---Event事件---定时器
死锁 互斥锁:Lock(),互斥锁只能acquire一次 递归锁: RLock(),可以连续acquire多次,每acquire一次计数器+1,只有计数为0时,才能被抢到acquire # 死锁 f ...
- python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03
目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...
- 8.14 day32 TCP服务端并发 GIL解释器锁 python多线程是否有用 死锁与递归锁 信号量event事件线程q
TCP服务端支持并发 解决方式:开多线程 服务端 基础版 import socket """ 服务端 1.要有固定的IP和PORT 2.24小时不间断提供服务 3.能够支 ...
- GIL全局解释器锁-死锁与递归锁-信号量-event事件
一.全局解释器锁GIL: 官方的解释:掌握概念为主 """ In CPython, the global interpreter lock, or GIL, is a m ...
- [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]
[并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...
- 递归锁,event事件和信号量
锁通常被用来实现对共享资源的同步访问.为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问 ...
- GIL 信号量 event事件 线程queue
GIL全局解释器锁 官方解释: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple n ...
- python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁
ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...
- python开发线程:死锁和递归锁&信号量&定时器&线程queue&事件evevt
一 死锁现象与递归锁 进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将 ...
随机推荐
- Acunetix临时扫描是不够的
Web漏洞扫描程序通常被视为即席工具.最初,所有漏洞扫描程序都是这种工具,并且当前的开源Web应用程序安全解决方案仍遵循该模型.但是,随着Web技术的复杂性和可用性的大幅增加,临时模型已经过时,无法满 ...
- CF1539D PriceFixed[题解]
PriceFixed 题目大意 市场上又 \(n\) 种商品,每种商品的价格都是 \(2\) .对于第 \(i\) 种商品 \(a_i\) 件.对于商品 \(i\) 给出一个值 \(b_i\) ,如果 ...
- 「SDOI2016」数字配对
「SDOI2016」数字配对 题目大意 传送门 题解 \(a_i\) 是 \(a_j\) 的倍数,且 \(\frac{a_i}{a_j}\) 是一个质数,则将 \(a_i,a_j\) 质因数分解后,其 ...
- ES6 模版字符串及常用的es6扩展方法
1.ES6 模版字符串es6 模版字符串主要用于简化字符串的拼接 <script type="text/javascript"> let obj={name:'rdb' ...
- python + pytest基本使用方法(断言)
#pytest 的基本用法# 安装: pip install pytest#在当前目录下运行 : 输入 pytest# 1.断言#功能:用于计算a与b相加的和def add(a,b): return ...
- 啥是 MySQL 事务隔离级别?
之前发过一篇文章,简单了解 MySQL 中相关的锁,里面提到了,如果我们使用的 MySQL 存储引擎为 InnoDB ,并且其事务隔离级别是 RR 可重复读的话,是可以避免幻读的. 但是没想到,都 1 ...
- spring的属性注入和构造器注入
spring在向IOC容器中注入Bean的时候,有三种注入方式: 属性注入构造器注入工厂方法注入平常中用到的前两种方法较多,下面对前两种方法举例.一.属性注入1.创建一个car类,作为注入的bean ...
- odoo前后端交互详解
为了简单叙述,暂时不考虑多个db的情况(主要是懒得说没有db或者多个db实例的情况)当odoo指定数据库开启服务时(也就是odoo-bin -d <some_db_name> ),我们使用 ...
- 深入刨析tomcat 之---第8篇 how tomcat works 第11章 11.9应用程序,自定义Filter,及注册
writed by 张艳涛, 标签:全网独一份, 自定义一个Filter 起因:在学习深入刨析tomcat的学习中,第11章,说了调用过滤链的原理,但没有给出实例来,自己经过分析,给出来了一个Filt ...
- frame window 和open 的关系
建立一个如下的关系框架 windowA.html <!DOCTYPE html> <html lang="en"> <head> <met ...