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 使用线程执 ...
随机推荐
- 5.LNMP(Linux + Nginx + MySQL + PHP)环境安装
1.安装Nginx: yum install yum-priorities -y wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-r ...
- node.js异步编程的几种模式
Node.js异步编程的几种模式 以读取文件为例: 1.callback function const fs = require('fs'); //callback function fs.readF ...
- MySQL GTID复制Slave跳过错误事务Id以及复制排错问题总结
GTID复制典型的复制错误有两种:1,数据对象级别的错误,包括主库上update的数据在从库上不存在,主从逐渐冲突,库表索引等对象的冲突等等, 如果是纯粹的跳过错误的话,这一类的错误需要跳过思路是 ...
- jquery通过AJAX从后台获取信息并显示在表格上,并支持行选中
不想用Easyui的样式,但是想要他的表格功能,本来一开始是要到网上找相关插件的,但是没找到就开始自己写,没想到这么简单. 后台代码:(这个不重要) public ActionResult GetDi ...
- servlet的继承关系
一.servlet的继承关系 1.servlet程序是sun公司开发用于web资源技术,任何一个类只需要实现了servlet接口,那么就可以成为servlet程序 2.继承体系: ---------- ...
- CentOS7 安装phpMyAdmin-4.8.3-all-languages
1 需要先安装好web服务(如nginx).PHP.数据库(如MySQL) 在此略过... wget -O /tmp/phpMyAdmin--all-languages.tar.gz https:// ...
- poj2777(线段树)
题目链接:https://vjudge.net/problem/POJ-2777 题意:有L块连续的板子,每块板子最多染一种颜色,有T种(<=30)颜色,刚开始将所有板子染成颜色1,O次操作(包 ...
- Hillstone设备管理-许可证安装
1.CLI命令行安装 登录安全网关,运行命令exec license install +许可证,如下图: 系统会提示重启后生效,重启设备即可. 2.web界面安装许可证 1)登录安全网关设备,依次点击 ...
- js-当前时间转换
new Date().toLocaleString() 数组转换过后
- vue-computed计算属性用法
siytem函数可以当做变量在html中展现,列:{{siytem}} v-for(item in siytem)遍历也可以. 这个函数是从获取到的数据中,得到值后再次提取里面的数据,通过下标 me ...