day 35 线程
内容回顾
# 互斥锁
#在同一个进程中连续锁多次 #进程的数据共享
#进程之间可以共享数据
#提供共享数据的类是Manager
#但是它提供的list|dict 这些数据类型
#针对+= -= *= -=
#需要加锁保证安全 # 进程之间的通信
# ipc:
#queue
#管道 #机制也可以数据通信
#manager
#lock #acquire acquire 还有一块空间 有锁的状态
#Process #开启时 # 进程锁 线程锁 #一个共享 一个锁就得通信 线程锁不锁得住 进程 # 线程
#概念
#进程和线程的区别
#进程 开销大 数据隔离
#是计算机中最小的资源分配单位
#线程 轻量级 共享数据
#是计算机中能被cpu调度的最小单位
#正常的线程是什么
#能同时被多个cpu执行 #Cpython解释器下的线程(解释器里有 锁只一个进程一个时刻会用)
#GIL锁
#全局解释器锁
#是CPython解释其中的
#会导致同一个时刻只能有一个线程 #代码 threading 模块
#Thread 类
#开启线程
#传参数
#没有terminate
#join
#active_count int 当前程序中正在执行的线程个数
#current_thread 线程对象 能够获取 当前线程 的对象 from multiprocessing import Process
class Myprocess(Process):
def __init__(self,args):
super().__init__()
self.args = args
def run(self):
print('子进程执行',self.name) p1 = Myprocess(1)
p1.start() #self指向p1 和p1 是一样的 #和 current_thread一样
p1.join() p2 = Myprocess(1)
p2.start() #self指向p2 #水性杨花
p2.join()
今日内容
# 守护线程
# threading.enumerate
# 线程锁
#互斥锁
#递归锁
#死锁现象
#线程队列
#进程池和线程池 3 不大对的enumeate 方法
#__author : 'liuyang'
#date : 2019/4/18 0018 上午 9:24
from threading import Thread, enumerate,active_count
def func():
print('in son thread')
Thread(target= func).start()
print(enumerate())
#[<_MainThread(MainThread, started 2788)>]
active_count = len(enumerate())
print(active_count)
老师讲
from threading import enumerate,Thread def func():
print('in son thread') Thread(target=func).start()
print(enumerate()) # 返回一个存储着所有线程对象的列表
# active_count = len(enumerate())
# [<_MainThread(MainThread, started 1200)>,
# <Thread(Thread-1, started 4156)>]
4守护线程
#__author : 'liuyang'
#date : 2019/4/18 0018 上午 9:27
from threading import Thread
import time
def daemon_func():
while True:
time.sleep(0.5)
print('守护线程') def son_func():
print("start son")
time.sleep(5)
print('end son')
t = Thread(target=daemon_func)
t.daemon = True
t.start()
Thread(target=son_func).start()
time.sleep(3)
print('主线程结束了') # 1. 主线程会等待子线程的结束而结束
# 2. 守护线程会随着主线程的结束而结束
#守护线程会守护主线程 和 所有的子线程 # 进程会随着 主线程的结束而结束
# 所有非守护线程终止,即使存在守护线程,进程运行终止
# 所有守护线程终止, # 问题
#1. 主线程需不需要回收子线程的资源
#不需要 , 线程资源属于进程, 所以进程结束了,线程的资源自然就被回收了
# 2 .主线程 为什么要等待子线程结束之后结束
# 主线程结束意味着进程结束,所有的子线程都会结束
# 要想让子线程能够顺利执行完,主线程只能等
#3 守护线程 到底要怎么结束的
#主线程结束了 进程也结束了 守护线程被主进程的结束结束掉了(守护了这个进程。。。) #守护进程: 只会守护到主进程的代码结束
#守护线程: 会守护到 所有其它非守护线程的结束
5 线程
还要加锁 ? GIL 的锁为了节省时间 没有很负责的锁住 浪费时间 只锁规定时间内(时间片)
#__author : 'liuyang'
#date : 2019/4/18 0018 上午 10:10
# 线程里有必要要锁么?
# GIL 和 锁的关系 #轮流执行一个 cpu from dis import dis
from threading import Thread,Lock count = 0
# count = []
l = []
def add_func(lock):
global count
for i in range(200000):
with lock :
count += 1
# count.append(1)
def sub_func(lock):
global count
with lock:
for i in range(200000):
count -= 1
# i = 200000
# while i >0 :
# if count:
# count.pop()
# i -= 1 def add_list():
l.append(1)
# dis(add_func)
t_l = []
lock = Lock()
# for i in range(5):
# t1 =Thread(target=add_func,args = (lock,))
# t1.start()
# t_l.append(t1)
# t2 =Thread(target=sub_func,args= (lock,))
# t2.start()
# t_l.append(t2)
# for t in t_l:t.join()
# print(count)
dis(add_list)
# 数据不安全 ''' 两个线程模拟 加载count 1 加载+ 存回全局变量
14 14 LOAD_GLOBAL 1 (count)
16 LOAD_CONST 2 (1)
18 INPLACE_ADD
20 STORE_GLOBAL 1 (count)
22 JUMP_ABSOLUTE 10
>> 24 POP_BLOCK
>> 26 LOAD_CONST 0 (None)
28 RETURN_VALUE''' # 当执行 STORE += 两步操作
# GIL 时间片 轮转 (700条 ):造成了数据不安全
#锁保证一个时间短一个线程 但是 没执行完 没存值
#不是python代码 而是底层cpu执行 # l.append(1)
''' lst.append(1) 原子性:不可再分性 [1,1]
30 0 LOAD_GLOBAL 0 (l)
2 LOAD_ATTR 1 (append)
4 LOAD_CONST 1 (1)
6 CALL_FUNCTION 1 # 调函数
8 POP_TOP #POP :出栈 #pop是弹出栈顶元素,top是获得栈顶元素,不弹出
10 LOAD_CONST 0 (None)
12 RETURN_VALUE''' # if [].pop() #两步操作 轮转了 改变了 没法pop了 所以报错
# += #两步操作 轮转了 没改变全局变量存到里面 所以有重叠 # 数据不安全
#在线程中也会出现数据不安全的
#1.对全局变量进行修改
#2.对某个值 += -= *= /=
# 通过加锁来解决 # 设计都写好的函数 修改的
# list pop append extend insert insert remove
# dict pop update
# list[0] += 1
# dic[key] -= 1 #list.pop/append # pop列表为空时会 报错
# queue put/get # get队列为空时会 等待 # GIL
#
# 如果没有GIL锁
# append(1) append(1) 多个cpu同时进行
# 在一个列表地址中 被覆盖了 # 1 . 有了GIL 保证了线程同一时刻只能有一个线程访问CPU,不可能有两个线程t同时在cpu上执行指令
# 没有GIL操作 任何小操作都得加锁 # 2 lock 锁 保证某一段代码 在没有执行完毕之后,不可能有另一个线程也执行它
# 时间片轮转
6 科学家吃面问题
两个人 两个东西 得二可得天下 但是一人一个
#__author : 'liuyang'
#date : 2019/4/18 0018 上午 10:54
#死锁: 永远解不开了才叫 # acquire # acquire 低级的死锁 好开
# '''
from threading import Lock
# 死锁代码 :操作两个变量的 两个函数同时使用两个变量 时机问题 我有叉子 你有面
# 自己代码没问题 没测到并发 很多线程 上线了服务
from threading import Thread #用户一多 多线程 死锁 阻在那了 不走了
noodle_lock = Lock()
fork_lock = Lock()
import time
def eat1(name):
noodle_lock.acquire()
print('%s 拿到面了'%name)
fork_lock.acquire()
print('%s 拿到叉子'%name)
print('%s 吃面'%name)
time.sleep(0.1)
fork_lock.release()
print('%s 放下茶子'%name)
noodle_lock.release()
print('%s 放下面'%name)
def eat2(name):
fork_lock.acquire()
print('%s 拿到叉子了'%name)
noodle_lock.acquire()
print('%s 拿到面了'%name)
print('%s 吃面'%name)
noodle_lock.release()
print('%s 放下面' % name)
fork_lock.release()
print('%s 放下茶子'%name) Thread(target=eat1 , args=('alex',)).start()
Thread(target=eat2 , args=('al',)).start()
Thread(target=eat1 , args=('ex',)).start() # '''
# 快速解决问题
#改成一把锁
#递归锁
# 门口挂着一串(万能)钥匙 (互斥一个钥匙)
#也是把两把锁并成 一把锁 ,别的结构不改
# 很多个门 #lock.acquire()
#拿到面了
#lock.acquire()
#拿到叉子
#吃面
#lock.release()
#放下面
#lock.release()
#放下叉子 #归还到最外层
#
# from threading import RLock , Lock
# lock = Lock()
# rlock = RLock() # lock.acquire()
# print(123)
# lock.acquire()
# print(456) # rlock.acquire()
# print(123)
# rlock.acquire()
# print(456)
# rlock.acquire()
# print(56) #万能钥匙 可以近很多个锁门 但是得出来
# rlock.release()
# rlock.release()
# rlock.release() # 搞两个锁都会锁 不管递归锁 # 在同一个线程中是不会出现数据安全(死锁) 的 所以 递归锁 可以
from threading import RLock , Lock,Thread
# fork_lock = noodle_lock = RLock()
# def eat1(name):
# noodle_lock.acquire()
# print('%s 拿到面了'%name)
# fork_lock.acquire()
# print('%s 拿到叉子'%name)
# print('%s 吃面'%name)
# fork_lock.release()
# print('%s 放下茶子'%name)
# noodle_lock.release()
# print('%s 放下面'%name)
# def eat2(name):
# noodle_lock.acquire()
# print('%s 拿到叉子了'%name)
# fork_lock.acquire()
# print('%s 拿到面子'%name)
# print('%s 吃面'%name)
# fork_lock.release()
# print('%s 放下茶子'%name)
# noodle_lock.release()
# print('%s 放下面'%name)
# Thread(target=eat1 , args=('l',)).start()
# Thread(target=eat1 , args=('y',)).start() # lock = Lock() #上面的效率低 改成 互斥锁
# def eat1(name): #最简单 没问题
# lock.acquire()
# print('%s 拿到面了'%name)
# print('%s 拿到叉子'%name)
# print('%s 吃面'%name)
# print('%s 放下茶子'%name)
# print('%s 放下面'%name)
# lock.release()
# def eat2(name):
# lock.acquire()
# print('%s 拿到面了'%name)
# print('%s 拿到叉子'%name)
# print('%s 吃面'%name)
# print('%s 放下茶子'%name)
# print('%s 放下面'%name)
# lock.release()
# Thread(target=eat1 , args=('l',)).start()
# Thread(target=eat1 , args=('y',)).start() #两个进程 各拿到一个 钥匙
#都完不成
# 你要操作的数据不止一个 a = 1 b = 2 c = a+b # a.acquire()
#忘了解锁 阻塞在某个点了 可能锁了
# b.acquire()
# a.release()
# b.release() # 出错了 改不出来了 就先把所有的锁 改成一个锁 没问题,但是效率不高
# 改好了, 再改一把把锁 # 获取锁 释放锁 不要把大段代码 放了锁里
#一把锁锁一个资源 # 死锁不是锁 #互斥锁
#递归锁
7.队列
#__author : 'liuyang'
#date : 2019/4/18 0018 下午 12:08
from queue import Queue
# Queue 就是一个线程队列的类, 自带 lock锁,实现了线程安全的数据类型
# 队列是一个线程安全的数据类型 放进去拿出来 # [][]+=1 不安全 列表
q = Queue()
q.put(1) #在多线程下都不准 异步没法控制
q.empty() #判断是否为空
q.full() #判断是否为满
q.qsize() #队列的大小 q.put({1,2,3})
q.get()
q.put_nowait({'abc'})
print(q.get_nowait()) #先进先出
print(q.get_nowait()) #先进后出 的 队列 last in first out
from queue import LifoQueue #栈 后进先出的时候 都可以用过
lfq = LifoQueue()
lfq.put(1)
lfq.put('abc')
lfq.put({'','','',''})
print(lfq.get())
print(lfq.get())
print(lfq.get()) # 栈从空间复杂度上来讲 栈的效率要比递归高
# 队列来讲顺序性 from queue import PriorityQueue #小的优先级高1 优先级队列
pq = PriorityQueue()
pq.put((1,'abcd'))
pq.put((2,'dcba'))
pq.put((20,'dddd'))
print(pq.get())
print(pq.get())
print(pq.get()) #设置成会员 抢票好 # 线程+队列 实现消费者生产者模型
8池 进程
#__author : 'liuyang'
#date : 2019/4/18 0018 下午 12:08
from queue import Queue
# Queue 就是一个线程队列的类, 自带 lock锁,实现了线程安全的数据类型
# 队列是一个线程安全的数据类型 放进去拿出来 # [][]+=1 不安全 列表
q = Queue()
q.put(1) #在多线程下都不准 异步没法控制
q.empty() #判断是否为空
q.full() #判断是否为满
q.qsize() #队列的大小 q.put({1,2,3})
q.get()
q.put_nowait({'abc'})
print(q.get_nowait()) #先进先出
print(q.get_nowait()) #先进后出 的 队列 last in first out
from queue import LifoQueue #栈 后进先出的时候 都可以用过
lfq = LifoQueue()
lfq.put(1)
lfq.put('abc')
lfq.put({'','','',''})
print(lfq.get())
print(lfq.get())
print(lfq.get()) # 栈从空间复杂度上来讲 栈的效率要比递归高
# 队列来讲顺序性 from queue import PriorityQueue #小的优先级高1 优先级队列
pq = PriorityQueue()
pq.put((1,'abcd'))
pq.put((2,'dcba'))
pq.put((20,'dddd'))
print(pq.get())
print(pq.get())
print(pq.get()) #设置成会员 抢票好 # 线程+队列 实现消费者生产者模型
9总结
# 守护线程
#锁
#互斥
#递归
#死锁现象 #队列 线程安全的数据
#先进先出 queue
#后进先出 LifoQueue
#优先级队列 PriorityQueue #池
#控制进程的数量
#节省资源开销
day 35 线程的更多相关文章
- 深入浅出 Java Concurrency (35): 线程池 part 8 线程池的实现及原理 (3)[转]
线程池任务执行结果 这一节来探讨下线程池中任务执行的结果以及如何阻塞线程.取消任务等等. 1 package info.imxylz.study.concurrency.future;2 3 publ ...
- Python 35 线程(2)线程特性、守护线程、线程互斥锁
一:线程特性介绍 from threading import Thread import time n=100 def task(): global n n=0 if __name__ == '__m ...
- Python 35 线程(1)线程理论、开启线程的两种方式
一:线程理论 1 什么是线程 进程其实一个资源单位,而进程内的线程才是cpu上的执行单位 线程其实指的就是代码的执行过程2 为何要用线程 线程vs进程 1. 同一进程下的多个线程共享该进程 ...
- Java线程:概念与原理
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- Java线程:线程状态的转换
Java线程:线程状态的转换 一.线程状态 线程的状态转换是线程控制的基础.线程状态总的可分为五大状态:分别是生.死.可运行.运行.等待/阻塞.用一个图来描述如下: 1.新状态:线程对象已 ...
- java线程详解
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- Java线程详解----借鉴
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- java 线程(1)
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- Java 线程的创建和启动
Java 使用 Thread 类代表线程,所有的线程对象都必须是 Thread 类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码). Java 使用线程执 ...
随机推荐
- JEECG 集成KiSSO单点登录实现统一身份认证
JEECG 集成KiSSO单点登录实现统一身份认证 JEECG 如何为其他第三方系统实现统一身份认证服务,实现单点登录? 第三方系统如何对接呢? 今天为大家揭开这层面纱,让大家了解实质,使用它更快速的 ...
- 干货!微信自动跳转默认浏览器下载app的方法!
现在微信渠道可以说是拉新最快的渠道,因为微信具备强裂变性.但是目前微信对第三方下载链接的拦截是越来越严格了,那么想要在微信内肆无忌惮地推广链接就需要用到微信跳转浏览器的接口,那如何获取该接口呢? ...
- 转 JVM找出占用CPU最高的线程
这两天客户这边有一台服务器一到下午3点左右就开始卡住,页面无法访问,服务器CPU占用达到300%多开始以为只是可能只是意外事件,重启一下就好,但是发现重启之后没几分钟服务器马上又反应无法访问,我就开始 ...
- POI--各种样式的XSSFCellStyle的生成
//背景色.フォント色.枠線より各種XSSFCellStyleの作成して.cellStyleMapに保存する private HashMap<String, XSSFCellStyle> ...
- (ZT)算法杂货铺——分类算法之朴素贝叶斯分类(Naive Bayesian classification)
https://www.cnblogs.com/leoo2sk/archive/2010/09/17/naive-bayesian-classifier.html 0.写在前面的话 我个人一直很喜欢算 ...
- Python开发者年度调研,结果出乎意料!
来源商业新知网,原标题:Python开发者年度调研:一半Python用户也用JS,2/3选择Linux系统 作为高级编程语言,Python的受欢迎程度近几年一直在往 上涨.每年,Python官方都会针 ...
- IDEAL启动项目的时候报java.lang.NoClassDefFoundError: javax/servlet/Filter错误
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...
- 数据仓库系列 - 缓慢渐变维度 (Slowly Changing Dimension) 常见的三种类型及原型设计
在从 OLTP 业务数据库向 DW 数据仓库抽取数据的过程中,特别是第一次导入之后的每一次增量抽取往往会遇到这样的问题:业务数据库中的一些数据发生了更改,到底要不要将这些变化也反映到数据仓库中?在数据 ...
- [邀月博客] SQL Server 2008中SQL增强之二:Top新用途
top数为变量时 declare @intTop intset @intTop=2print @intTop --set rowcount @intTop--select * from [dbo].[ ...
- Linux-01
Linux各目录的作用 /bin/ 存放系统命令的目录,普通用户和超级用户都可以执行.不过放在/bin下的命令在单用户模式下也可以执行 /sbin/ 保存和系统环境设置相关的命令,只有超级用户可以使用 ...