内容回顾

  1. # 互斥锁
  2. #在同一个进程中连续锁多次
  3.  
  4. #进程的数据共享
  5. #进程之间可以共享数据
  6. #提供共享数据的类是Manager
  7. #但是它提供的list|dict 这些数据类型
  8. #针对+= -= *= -=
  9. #需要加锁保证安全
  10.  
  11. # 进程之间的通信
  12. # ipc:
  13. #queue
  14. #管道
  15.  
  16. #机制也可以数据通信
  17. #manager
  18. #lock #acquire acquire 还有一块空间 有锁的状态
  19. #Process #开启时
  20.  
  21. # 进程锁 线程锁 #一个共享 一个锁就得通信 线程锁不锁得住 进程
  22.  
  23. # 线程
  24. #概念
  25. #进程和线程的区别
  26. #进程 开销大 数据隔离
  27. #是计算机中最小的资源分配单位
  28. #线程 轻量级 共享数据
  29. #是计算机中能被cpu调度的最小单位
  30. #正常的线程是什么
  31. #能同时被多个cpu执行
  32.  
  33. #Cpython解释器下的线程(解释器里有 锁只一个进程一个时刻会用)
  34. #GIL锁
  35. #全局解释器锁
  36. #是CPython解释其中的
  37. #会导致同一个时刻只能有一个线程
  38.  
  39. #代码 threading 模块
  40. #Thread 类
  41. #开启线程
  42. #传参数
  43. #没有terminate
  44. #join
  45. #active_count int 当前程序中正在执行的线程个数
  46. #current_thread 线程对象 能够获取 当前线程 的对象
  47.  
  48. from multiprocessing import Process
  49. class Myprocess(Process):
  50. def __init__(self,args):
  51. super().__init__()
  52. self.args = args
  53. def run(self):
  54. print('子进程执行',self.name)
  55.  
  56. p1 = Myprocess(1)
  57. p1.start() #self指向p1 和p1 是一样的 #和 current_thread一样
  58. p1.join()
  59.  
  60. p2 = Myprocess(1)
  61. p2.start() #self指向p2 #水性杨花
  62. p2.join()

今日内容

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

老师讲

  1. from threading import enumerate,Thread
  2.  
  3. def func():
  4. print('in son thread')
  5.  
  6. Thread(target=func).start()
  7. print(enumerate()) # 返回一个存储着所有线程对象的列表
  8. # active_count = len(enumerate())
  9. # [<_MainThread(MainThread, started 1200)>,
  10. # <Thread(Thread-1, started 4156)>]

4守护线程

  1. #__author : 'liuyang'
  2. #date : 2019/4/18 0018 上午 9:27
  3. from threading import Thread
  4. import time
  5. def daemon_func():
  6. while True:
  7. time.sleep(0.5)
  8. print('守护线程')
  9.  
  10. def son_func():
  11. print("start son")
  12. time.sleep(5)
  13. print('end son')
  14. t = Thread(target=daemon_func)
  15. t.daemon = True
  16. t.start()
  17. Thread(target=son_func).start()
  18. time.sleep(3)
  19. print('主线程结束了')
  20.  
  21. # 1. 主线程会等待子线程的结束而结束
  22. # 2. 守护线程会随着主线程的结束而结束
  23. #守护线程会守护主线程 和 所有的子线程
  24.  
  25. # 进程会随着 主线程的结束而结束
  26. # 所有非守护线程终止,即使存在守护线程,进程运行终止
  27. # 所有守护线程终止,
  28.  
  29. # 问题
  30. #1. 主线程需不需要回收子线程的资源
  31. #不需要 , 线程资源属于进程, 所以进程结束了,线程的资源自然就被回收了
  32. # 2 .主线程 为什么要等待子线程结束之后结束
  33. # 主线程结束意味着进程结束,所有的子线程都会结束
  34. # 要想让子线程能够顺利执行完,主线程只能等
  35. #3 守护线程 到底要怎么结束的
  36. #主线程结束了 进程也结束了 守护线程被主进程的结束结束掉了(守护了这个进程。。。)
  37.  
  38. #守护进程: 只会守护到主进程的代码结束
  39. #守护线程: 会守护到 所有其它非守护线程的结束

5 线程

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

  1. #__author : 'liuyang'
  2. #date : 2019/4/18 0018 上午 10:10
  3. # 线程里有必要要锁么?
  4. # GIL 和 锁的关系 #轮流执行一个 cpu
  5.  
  6. from dis import dis
  7. from threading import Thread,Lock
  8.  
  9. count = 0
  10. # count = []
  11. l = []
  12. def add_func(lock):
  13. global count
  14. for i in range(200000):
  15. with lock :
  16. count += 1
  17. # count.append(1)
  18. def sub_func(lock):
  19. global count
  20. with lock:
  21. for i in range(200000):
  22. count -= 1
  23. # i = 200000
  24. # while i >0 :
  25. # if count:
  26. # count.pop()
  27. # i -= 1
  28.  
  29. def add_list():
  30. l.append(1)
  31. # dis(add_func)
  32. t_l = []
  33. lock = Lock()
  34. # for i in range(5):
  35. # t1 =Thread(target=add_func,args = (lock,))
  36. # t1.start()
  37. # t_l.append(t1)
  38. # t2 =Thread(target=sub_func,args= (lock,))
  39. # t2.start()
  40. # t_l.append(t2)
  41. # for t in t_l:t.join()
  42. # print(count)
  43. dis(add_list)
  44. # 数据不安全
  45.  
  46. ''' 两个线程模拟 加载count 1 加载+ 存回全局变量
  47. 14 14 LOAD_GLOBAL 1 (count)
  48. 16 LOAD_CONST 2 (1)
  49. 18 INPLACE_ADD
  50. 20 STORE_GLOBAL 1 (count)
  51. 22 JUMP_ABSOLUTE 10
  52. >> 24 POP_BLOCK
  53. >> 26 LOAD_CONST 0 (None)
  54. 28 RETURN_VALUE'''
  55.  
  56. # 当执行 STORE += 两步操作
  57. # GIL 时间片 轮转 (700条 ):造成了数据不安全
  58. #锁保证一个时间短一个线程 但是 没执行完 没存值
  59. #不是python代码 而是底层cpu执行
  60.  
  61. # l.append(1)
  62. ''' lst.append(1) 原子性:不可再分性 [1,1]
  63. 30 0 LOAD_GLOBAL 0 (l)
  64. 2 LOAD_ATTR 1 (append)
  65. 4 LOAD_CONST 1 (1)
  66. 6 CALL_FUNCTION 1 # 调函数
  67. 8 POP_TOP #POP :出栈 #pop是弹出栈顶元素,top是获得栈顶元素,不弹出
  68. 10 LOAD_CONST 0 (None)
  69. 12 RETURN_VALUE'''
  70.  
  71. # if [].pop() #两步操作 轮转了 改变了 没法pop了 所以报错
  72. # += #两步操作 轮转了 没改变全局变量存到里面 所以有重叠
  73.  
  74. # 数据不安全
  75. #在线程中也会出现数据不安全的
  76. #1.对全局变量进行修改
  77. #2.对某个值 += -= *= /=
  78. # 通过加锁来解决
  79.  
  80. # 设计都写好的函数 修改的
  81. # list pop append extend insert insert remove
  82. # dict pop update
  83. # list[0] += 1
  84. # dic[key] -= 1
  85.  
  86. #list.pop/append # pop列表为空时会 报错
  87. # queue put/get # get队列为空时会 等待
  88.  
  89. # GIL
  90. #
  91. # 如果没有GIL锁
  92. # append(1) append(1) 多个cpu同时进行
  93. # 在一个列表地址中 被覆盖了
  94.  
  95. # 1 . 有了GIL 保证了线程同一时刻只能有一个线程访问CPU,不可能有两个线程t同时在cpu上执行指令
  96. # 没有GIL操作 任何小操作都得加锁
  97.  
  98. # 2 lock 锁 保证某一段代码 在没有执行完毕之后,不可能有另一个线程也执行它
  99. # 时间片轮转

6 科学家吃面问题

两个人 两个东西 得二可得天下 但是一人一个

  1. #__author : 'liuyang'
  2. #date : 2019/4/18 0018 上午 10:54
  3. #死锁: 永远解不开了才叫
  4.  
  5. # acquire # acquire 低级的死锁 好开
  6. # '''
  7. from threading import Lock
  8. # 死锁代码 :操作两个变量的 两个函数同时使用两个变量 时机问题 我有叉子 你有面
  9. # 自己代码没问题 没测到并发 很多线程 上线了服务
  10. from threading import Thread #用户一多 多线程 死锁 阻在那了 不走了
  11. noodle_lock = Lock()
  12. fork_lock = Lock()
  13. import time
  14. def eat1(name):
  15. noodle_lock.acquire()
  16. print('%s 拿到面了'%name)
  17. fork_lock.acquire()
  18. print('%s 拿到叉子'%name)
  19. print('%s 吃面'%name)
  20. time.sleep(0.1)
  21. fork_lock.release()
  22. print('%s 放下茶子'%name)
  23. noodle_lock.release()
  24. print('%s 放下面'%name)
  25. def eat2(name):
  26. fork_lock.acquire()
  27. print('%s 拿到叉子了'%name)
  28. noodle_lock.acquire()
  29. print('%s 拿到面了'%name)
  30. print('%s 吃面'%name)
  31. noodle_lock.release()
  32. print('%s 放下面' % name)
  33. fork_lock.release()
  34. print('%s 放下茶子'%name)
  35.  
  36. Thread(target=eat1 , args=('alex',)).start()
  37. Thread(target=eat2 , args=('al',)).start()
  38. Thread(target=eat1 , args=('ex',)).start()
  39.  
  40. # '''
  41. # 快速解决问题
  42. #改成一把锁
  43. #递归锁
  44. # 门口挂着一串(万能)钥匙 (互斥一个钥匙)
  45. #也是把两把锁并成 一把锁 ,别的结构不改
  46. # 很多个门
  47.  
  48. #lock.acquire()
  49. #拿到面了
  50. #lock.acquire()
  51. #拿到叉子
  52. #吃面
  53. #lock.release()
  54. #放下面
  55. #lock.release()
  56. #放下叉子 #归还到最外层
  57. #
  58. # from threading import RLock , Lock
  59. # lock = Lock()
  60. # rlock = RLock()
  61.  
  62. # lock.acquire()
  63. # print(123)
  64. # lock.acquire()
  65. # print(456)
  66.  
  67. # rlock.acquire()
  68. # print(123)
  69. # rlock.acquire()
  70. # print(456)
  71. # rlock.acquire()
  72. # print(56) #万能钥匙 可以近很多个锁门 但是得出来
  73. # rlock.release()
  74. # rlock.release()
  75. # rlock.release()
  76.  
  77. # 搞两个锁都会锁 不管递归锁
  78.  
  79. # 在同一个线程中是不会出现数据安全(死锁) 的 所以 递归锁 可以
  80. from threading import RLock , Lock,Thread
  81. # fork_lock = noodle_lock = RLock()
  82. # def eat1(name):
  83. # noodle_lock.acquire()
  84. # print('%s 拿到面了'%name)
  85. # fork_lock.acquire()
  86. # print('%s 拿到叉子'%name)
  87. # print('%s 吃面'%name)
  88. # fork_lock.release()
  89. # print('%s 放下茶子'%name)
  90. # noodle_lock.release()
  91. # print('%s 放下面'%name)
  92. # def eat2(name):
  93. # noodle_lock.acquire()
  94. # print('%s 拿到叉子了'%name)
  95. # fork_lock.acquire()
  96. # print('%s 拿到面子'%name)
  97. # print('%s 吃面'%name)
  98. # fork_lock.release()
  99. # print('%s 放下茶子'%name)
  100. # noodle_lock.release()
  101. # print('%s 放下面'%name)
  102. # Thread(target=eat1 , args=('l',)).start()
  103. # Thread(target=eat1 , args=('y',)).start()
  104.  
  105. # lock = Lock() #上面的效率低 改成 互斥锁
  106. # def eat1(name): #最简单 没问题
  107. # lock.acquire()
  108. # print('%s 拿到面了'%name)
  109. # print('%s 拿到叉子'%name)
  110. # print('%s 吃面'%name)
  111. # print('%s 放下茶子'%name)
  112. # print('%s 放下面'%name)
  113. # lock.release()
  114. # def eat2(name):
  115. # lock.acquire()
  116. # print('%s 拿到面了'%name)
  117. # print('%s 拿到叉子'%name)
  118. # print('%s 吃面'%name)
  119. # print('%s 放下茶子'%name)
  120. # print('%s 放下面'%name)
  121. # lock.release()
  122. # Thread(target=eat1 , args=('l',)).start()
  123. # Thread(target=eat1 , args=('y',)).start()
  124.  
  125. #两个进程 各拿到一个 钥匙
  126. #都完不成
  127. # 你要操作的数据不止一个 a = 1 b = 2 c = a+b
  128.  
  129. # a.acquire()
  130. #忘了解锁 阻塞在某个点了 可能锁了
  131. # b.acquire()
  132. # a.release()
  133. # b.release()
  134.  
  135. # 出错了 改不出来了 就先把所有的锁 改成一个锁 没问题,但是效率不高
  136. # 改好了, 再改一把把锁
  137.  
  138. # 获取锁 释放锁 不要把大段代码 放了锁里
  139. #一把锁锁一个资源
  140.  
  141. # 死锁不是锁
  142.  
  143. #互斥锁
  144. #递归锁

7.队列

  1. #__author : 'liuyang'
  2. #date : 2019/4/18 0018 下午 12:08
  3. from queue import Queue
  4. # Queue 就是一个线程队列的类, 自带 lock锁,实现了线程安全的数据类型
  5. # 队列是一个线程安全的数据类型 放进去拿出来
  6.  
  7. # [][]+=1 不安全 列表
  8. q = Queue()
  9. q.put(1)
  10.  
  11. #在多线程下都不准 异步没法控制
  12. q.empty() #判断是否为空
  13. q.full() #判断是否为满
  14. q.qsize() #队列的大小
  15.  
  16. q.put({1,2,3})
  17. q.get()
  18. q.put_nowait({'abc'})
  19. print(q.get_nowait()) #先进先出
  20. print(q.get_nowait())
  21.  
  22. #先进后出 的 队列 last in first out
  23. from queue import LifoQueue #栈 后进先出的时候 都可以用过
  24. lfq = LifoQueue()
  25. lfq.put(1)
  26. lfq.put('abc')
  27. lfq.put({'','','',''})
  28. print(lfq.get())
  29. print(lfq.get())
  30. print(lfq.get())
  31.  
  32. # 栈从空间复杂度上来讲 栈的效率要比递归高
  33. # 队列来讲顺序性
  34.  
  35. from queue import PriorityQueue #小的优先级高1 优先级队列
  36. pq = PriorityQueue()
  37. pq.put((1,'abcd'))
  38. pq.put((2,'dcba'))
  39. pq.put((20,'dddd'))
  40. print(pq.get())
  41. print(pq.get())
  42. print(pq.get()) #设置成会员 抢票好
  43.  
  44. # 线程+队列 实现消费者生产者模型

8池 进程

  1. #__author : 'liuyang'
  2. #date : 2019/4/18 0018 下午 12:08
  3. from queue import Queue
  4. # Queue 就是一个线程队列的类, 自带 lock锁,实现了线程安全的数据类型
  5. # 队列是一个线程安全的数据类型 放进去拿出来
  6.  
  7. # [][]+=1 不安全 列表
  8. q = Queue()
  9. q.put(1)
  10.  
  11. #在多线程下都不准 异步没法控制
  12. q.empty() #判断是否为空
  13. q.full() #判断是否为满
  14. q.qsize() #队列的大小
  15.  
  16. q.put({1,2,3})
  17. q.get()
  18. q.put_nowait({'abc'})
  19. print(q.get_nowait()) #先进先出
  20. print(q.get_nowait())
  21.  
  22. #先进后出 的 队列 last in first out
  23. from queue import LifoQueue #栈 后进先出的时候 都可以用过
  24. lfq = LifoQueue()
  25. lfq.put(1)
  26. lfq.put('abc')
  27. lfq.put({'','','',''})
  28. print(lfq.get())
  29. print(lfq.get())
  30. print(lfq.get())
  31.  
  32. # 栈从空间复杂度上来讲 栈的效率要比递归高
  33. # 队列来讲顺序性
  34.  
  35. from queue import PriorityQueue #小的优先级高1 优先级队列
  36. pq = PriorityQueue()
  37. pq.put((1,'abcd'))
  38. pq.put((2,'dcba'))
  39. pq.put((20,'dddd'))
  40. print(pq.get())
  41. print(pq.get())
  42. print(pq.get()) #设置成会员 抢票好
  43.  
  44. # 线程+队列 实现消费者生产者模型

9总结

  1. # 守护线程
  2. #锁
  3. #互斥
  4. #递归
  5. #死锁现象
  6.  
  7. #队列 线程安全的数据
  8. #先进先出 queue
  9. #后进先出 LifoQueue
  10. #优先级队列 PriorityQueue
  11.  
  12. #池
  13. #控制进程的数量
  14. #节省资源开销

day 35 线程的更多相关文章

  1. 深入浅出 Java Concurrency (35): 线程池 part 8 线程池的实现及原理 (3)[转]

    线程池任务执行结果 这一节来探讨下线程池中任务执行的结果以及如何阻塞线程.取消任务等等. 1 package info.imxylz.study.concurrency.future;2 3 publ ...

  2. Python 35 线程(2)线程特性、守护线程、线程互斥锁

    一:线程特性介绍 from threading import Thread import time n=100 def task(): global n n=0 if __name__ == '__m ...

  3. Python 35 线程(1)线程理论、开启线程的两种方式

    一:线程理论 1 什么是线程 进程其实一个资源单位,而进程内的线程才是cpu上的执行单位 线程其实指的就是代码的执行过程2 为何要用线程   线程vs进程     1. 同一进程下的多个线程共享该进程 ...

  4. Java线程:概念与原理

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  5. Java线程:线程状态的转换

    Java线程:线程状态的转换   一.线程状态   线程的状态转换是线程控制的基础.线程状态总的可分为五大状态:分别是生.死.可运行.运行.等待/阻塞.用一个图来描述如下:   1.新状态:线程对象已 ...

  6. java线程详解

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  7. Java线程详解----借鉴

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  8. java 线程(1)

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  9. Java 线程的创建和启动

    Java 使用 Thread 类代表线程,所有的线程对象都必须是 Thread 类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码). Java 使用线程执 ...

随机推荐

  1. 5.LNMP(Linux + Nginx + MySQL + PHP)环境安装

    1.安装Nginx: yum install yum-priorities -y wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-r ...

  2. node.js异步编程的几种模式

    Node.js异步编程的几种模式 以读取文件为例: 1.callback function const fs = require('fs'); //callback function fs.readF ...

  3. MySQL GTID复制Slave跳过错误事务Id以及复制排错问题总结

    GTID复制典型的复制错误有两种:1,数据对象级别的错误,包括主库上update的数据在从库上不存在,主从逐渐冲突,库表索引等对象的冲突等等,   如果是纯粹的跳过错误的话,这一类的错误需要跳过思路是 ...

  4. jquery通过AJAX从后台获取信息并显示在表格上,并支持行选中

    不想用Easyui的样式,但是想要他的表格功能,本来一开始是要到网上找相关插件的,但是没找到就开始自己写,没想到这么简单. 后台代码:(这个不重要) public ActionResult GetDi ...

  5. servlet的继承关系

    一.servlet的继承关系 1.servlet程序是sun公司开发用于web资源技术,任何一个类只需要实现了servlet接口,那么就可以成为servlet程序 2.继承体系: ---------- ...

  6. CentOS7 安装phpMyAdmin-4.8.3-all-languages

    1 需要先安装好web服务(如nginx).PHP.数据库(如MySQL) 在此略过... wget -O /tmp/phpMyAdmin--all-languages.tar.gz https:// ...

  7. poj2777(线段树)

    题目链接:https://vjudge.net/problem/POJ-2777 题意:有L块连续的板子,每块板子最多染一种颜色,有T种(<=30)颜色,刚开始将所有板子染成颜色1,O次操作(包 ...

  8. Hillstone设备管理-许可证安装

    1.CLI命令行安装 登录安全网关,运行命令exec license install +许可证,如下图: 系统会提示重启后生效,重启设备即可. 2.web界面安装许可证 1)登录安全网关设备,依次点击 ...

  9. js-当前时间转换

    new Date().toLocaleString() 数组转换过后

  10. vue-computed计算属性用法

    siytem函数可以当做变量在html中展现,列:{{siytem}}  v-for(item in siytem)遍历也可以. 这个函数是从获取到的数据中,得到值后再次提取里面的数据,通过下标 me ...