博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
day 35 线程
阅读量:5138 次
发布时间:2019-06-13

本文共 9704 字,大约阅读时间需要 32 分钟。

 

内容回顾

 

 

# 互斥锁    #在同一个进程中连续锁多次#进程的数据共享    #进程之间可以共享数据    #提供共享数据的类是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 Processclass 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()
View Code

今日内容

# 守护线程 # threading.enumerate # 线程锁 #互斥锁 #递归锁 #死锁现象 #线程队列 #进程池和线程池 3 不大对的enumeate 方法
#__author : 'liuyang' #date : 2019/4/18 0018 上午 9:24from threading import Thread, enumerate,active_countdef func():    print('in son thread')Thread(target= func).start()print(enumerate())#[<_MainThread(MainThread, started 2788)>]active_count = len(enumerate())print(active_count)
View Code

老师讲

from threading import enumerate,Threaddef func():    print('in son thread')Thread(target=func).start()print(enumerate()) # 返回一个存储着所有线程对象的列表# active_count = len(enumerate())# [<_MainThread(MainThread, started 1200)>,# 
]
View Code

 

4守护线程

#__author : 'liuyang' #date : 2019/4/18 0018 上午 9:27from threading import Threadimport timedef 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 = Truet.start()Thread(target=son_func).start()time.sleep(3)print('主线程结束了')# 1. 主线程会等待子线程的结束而结束# 2. 守护线程会随着主线程的结束而结束    #守护线程会守护主线程 和 所有的子线程# 进程会随着 主线程的结束而结束    # 所有非守护线程终止,即使存在守护线程,进程运行终止    # 所有守护线程终止,# 问题    #1. 主线程需不需要回收子线程的资源        #不需要  , 线程资源属于进程, 所以进程结束了,线程的资源自然就被回收了    # 2 .主线程 为什么要等待子线程结束之后结束        # 主线程结束意味着进程结束,所有的子线程都会结束        # 要想让子线程能够顺利执行完,主线程只能等    #3 守护线程 到底要怎么结束的        #主线程结束了 进程也结束了 守护线程被主进程的结束结束掉了(守护了这个进程。。。)#守护进程: 只会守护到主进程的代码结束#守护线程: 会守护到 所有其它非守护线程的结束
View Code

 

5 线程

  还要加锁 ? GIL 的锁为了节省时间  没有很负责的锁住 浪费时间 只锁规定时间内(时间片)

#__author : 'liuyang' #date : 2019/4/18 0018 上午 10:10# 线程里有必要要锁么?# GIL 和 锁的关系        #轮流执行一个  cpufrom dis import disfrom threading import Thread,Lockcount = 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 -= 1def 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 锁 保证某一段代码 在没有执行完毕之后,不可能有另一个线程也执行它# 时间片轮转
View Code

 

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 timedef 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()# 出错了 改不出来了  就先把所有的锁  改成一个锁   没问题,但是效率不高# 改好了, 再改一把把锁# 获取锁  释放锁   不要把大段代码 放了锁里    #一把锁锁一个资源# 死锁不是锁#互斥锁#递归锁
View Code

 

7.队列

#__author : 'liuyang' #date : 2019/4/18 0018 下午 12:08from 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 outfrom queue import LifoQueue #栈 后进先出的时候 都可以用过lfq = LifoQueue()lfq.put(1)lfq.put('abc')lfq.put({
'1','2','3','4'})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()) #设置成会员 抢票好# 线程+队列 实现消费者生产者模型
View Code

 

8池 进程

#__author : 'liuyang' #date : 2019/4/18 0018 下午 12:08from 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 outfrom queue import LifoQueue #栈 后进先出的时候 都可以用过lfq = LifoQueue()lfq.put(1)lfq.put('abc')lfq.put({
'1','2','3','4'})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()) #设置成会员 抢票好# 线程+队列 实现消费者生产者模型
View Code

 

9总结

# 守护线程#锁    #互斥    #递归    #死锁现象#队列  线程安全的数据    #先进先出  queue    #后进先出   LifoQueue    #优先级队列  PriorityQueue#池    #控制进程的数量    #节省资源开销

 

转载于:https://www.cnblogs.com/Doner/p/10729084.html

你可能感兴趣的文章
(tmp >> 8) & 0xff;
查看>>
linux命令之ifconfig详细解释
查看>>
NAT地址转换
查看>>
Nhibernate 过长的字符串报错 dehydration property
查看>>
Deque - leetcode 【双端队列】
查看>>
gulp插件gulp-ruby-sass和livereload插件
查看>>
免费的大数据学习资料,这一份就足够
查看>>
clientWidth、clientHeight、offsetWidth、offsetHeight以及scrollWidth、scrollHeight
查看>>
企业级应用与互联网应用的区别
查看>>
itext jsp页面打印
查看>>
Perl正则表达式匹配
查看>>
DB Change
查看>>
nginx --rhel6.5
查看>>
Eclipse Python插件 PyDev
查看>>
selenium+python3模拟键盘实现粘贴、复制
查看>>
网站搭建(一)
查看>>
Spring JDBCTemplate
查看>>
Radon变换——MATLAB
查看>>
Iroha and a Grid AtCoder - 1974(思维水题)
查看>>
gzip
查看>>