线程的开启方法

进程是操作系统调度的最小单位,一个进程最少有一个主线程,而一个进程中可以开启多个线程

  1. from threading import Thread
  2. def task():
  3. print('A child thread')
  4. if __name__ == '__main__': # 这里是可以不用写的,但是规范起见还是写了
  5. t = Thread(target=task)
  6. t.start()
  7. print('==>main thread')

GIL锁

  1. """
  2. 1. Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行
  3. 2. Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。
  4. 1、GIL锁它是在python解释器中的, 只在cpython中有, pypy解释器是没有GIL锁的,
  5. 2、起一个垃圾回收线程, 一个是正常执行的线程
  6. 3、设置了一把锁(GIL锁), 一个线程要想执行,必须拿到这把锁
  7. 4、同一时刻,开启一个进程,一个进程中可以有多个线程, 只能有一个线程在执行
  8. 5、如果是计算密集型:要开进程
  9. 6、如果是io密集型:要开线程
  10. """

进程与线程的比较

线程与进程的区别可以归纳为以下4点:

  1. 地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
  2. 通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
  3. 调度和切换:线程上下文切换比进程上下文切换要快得多。
  4. 在多线程操作系统中,进程不是一个可执行的实体。

进程消耗的资源比线程要大的多,相对的,调用起来也比线程要慢

  1. # 进程调用时间演示
  2. import time
  3. from multiprocessing import Process
  4. def task():
  5. time.sleep(1)
  6. print('A child process')
  7. if __name__ == '__main__':
  8. start = time.time()
  9. p = Process(target=task)
  10. p.start()
  11. p.join()
  12. print('master process')
  13. print(time.time() - start)
  14. # 输出结果
  15. # A child process
  16. # master process
  17. # 1.069324016571045
  1. # 线程调用时间演示
  2. import time
  3. from threading import Thread
  4. def task():
  5. time.sleep(1)
  6. print('A child thread')
  7. if __name__ == '__main__':
  8. start = time.time()
  9. t = Thread(target=task)
  10. t.start()
  11. t.join()
  12. print('==>main thread')
  13. print(time.time()-start)
  14. # 输出结果
  15. # A child thread
  16. # ==>main thread
  17. # 1.005803108215332

线程间的数据是共享的

  1. def task():
  2. global n
  3. n=0
  4. if __name__ == '__main__':
  5. n=1
  6. t=Thread(target=task)
  7. t.start()
  8. t.join()
  9. print('主',n) # 查看结果为0,因为同一进程内的线程之间共享进程内的数据

Thread类的方法

  1. t.is_alive() # 返回线程是否活动
  2. t.getName() # 获取线程名
  3. t.setName() # 更新线程名
  4. threading.currentThread() # 返回当前的线程变量
  5. threading.enumerate() # 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程
  6. threading.activeCount() # 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

守护线程

  1. from threading import Thread
  2. import time
  3. def task():
  4. time.sleep(1)
  5. print("我是子线程")
  6. if __name__ == '__main__':
  7. t = Thread(target=task,)
  8. t.setDaemon(True) # 开启守护线程, 主线程结束,子线程跟着结束
  9. t.start()
  10. print("主线程")

线程互斥锁

  1. from threading import Thread,Lock
  2. import time
  3. import random
  4. def task(lock):
  5. #上锁
  6. lock.acquire()
  7. global n
  8. # 10个线程同时涌入导致数据不安全
  9. time.sleep(random.random())
  10. n -= 1
  11. # 释放锁
  12. lock.release()
  13. if __name__ == '__main__':
  14. start = time.time()
  15. lock = Lock()
  16. n = 100
  17. l = []
  18. for i in range(10):
  19. t = Thread(target=task,args=(lock,))
  20. t.start()
  21. l.append(t)
  22. for j in l:
  23. j.join()
  24. print('运算完毕:n = %s' %n)
  25. print(time.time()-start)

信号量

  1. from threading import Thread,Semaphore
  2. import time
  3. def task(i, sm):
  4. # 上锁
  5. sm.acquire()
  6. print("%s:这个人开始上厕所了" % i)
  7. time.sleep(3)
  8. print("%s:这个人上完了" % i)
  9. # 释放锁
  10. sm.release()
  11. # Semaphore:信号量可以理解为多把锁,同时允许多个线程来更改数据
  12. if __name__ == '__main__':
  13. sm = Semaphore(2) #
  14. for i in range(10):
  15. t = Thread(target=task, args=(i, sm))
  16. t.start()

Event事件

  1. from threading import Thread, Event
  2. import time
  3. def girl(event):
  4. print("都女士正在恋爱中...")
  5. time.sleep(3)
  6. print("都女生分手了")
  7. # 发出分手的信号
  8. event.set()
  9. def boy(i, event):
  10. print("渣男:%s正在等待都女生分手" % i)
  11. # 卡住
  12. event.wait()
  13. print("渣男:%s开始追了" % i)
  14. if __name__ == '__main__':
  15. event = Event()
  16. t = Thread(target=girl, args=(event,))
  17. t.start()
  18. for i in range(10):
  19. b_t = Thread(target=boy, args=(i, event))
  20. b_t.start()

释放出信号,而读数据课以收信号,一旦示范出可以读的信号该线程才会运行

线程 Thread类 GIL锁 信号量 Event事件的更多相关文章

  1. 并发编程---死锁||递归锁---信号量---Event事件---定时器

    死锁 互斥锁:Lock(),互斥锁只能acquire一次 递归锁:  RLock(),可以连续acquire多次,每acquire一次计数器+1,只有计数为0时,才能被抢到acquire # 死锁 f ...

  2. python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03

    目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...

  3. 8.14 day32 TCP服务端并发 GIL解释器锁 python多线程是否有用 死锁与递归锁 信号量event事件线程q

    TCP服务端支持并发 解决方式:开多线程 服务端 基础版 import socket """ 服务端 1.要有固定的IP和PORT 2.24小时不间断提供服务 3.能够支 ...

  4. GIL全局解释器锁-死锁与递归锁-信号量-event事件

    一.全局解释器锁GIL: 官方的解释:掌握概念为主 """ In CPython, the global interpreter lock, or GIL, is a m ...

  5. [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]

    [并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...

  6. 递归锁,event事件和信号量

    锁通常被用来实现对共享资源的同步访问.为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问 ...

  7. GIL 信号量 event事件 线程queue

    GIL全局解释器锁 官方解释: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple n ...

  8. python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

    ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...

  9. python开发线程:死锁和递归锁&信号量&定时器&线程queue&事件evevt

    一 死锁现象与递归锁 进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将 ...

随机推荐

  1. XCTF EasyRE

    一.查壳 无壳,并且发现是vc++编译的 二.拖入ida,来静态分析,这题让我深刻感觉到汇编的nb. 这段算是灵性的一段了,单从静态语句来看,发现分析不出啥,只能靠猜一下,我当时猜的是将输入的字符串又 ...

  2. c语言:随机函数应用

    #include <stdio.h> #include <time.h>//声明time 时间不可逆转一直在变 #include <math.h> #include ...

  3. Docker搭建Redis5.0并挂载数据

    记录 Docker 搭建 Redis5.0 并挂载数据过程,搭建参考自 Docker Hub 系列文章欢迎访问:https://www.itwxe.com/posts/9e76db89/ 一.简单挂载 ...

  4. Java集合中的可变参数

    可变参数: 1.在JDK1.5之后,如果我们定义一个方法需要接收多个参数,并且多个参数类型一致,我们可以对其简化成如下格式: 修饰符 返回值类型 方法名(参数类型... 形参名){} 其实这个书写完全 ...

  5. 【LeetCode】389.找不同

    389.找不同 知识点:哈希表.抵消思想: 题目描述 给定两个字符串 s 和 t,它们只包含小写字母. 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母. 请找出在 t 中被添加的字母. ...

  6. MapReduce学习总结之java版wordcount实现

    一.代码实现: package rdb.com.hadoop01.mapreduce; import java.io.IOException; import org.apache.hadoop.con ...

  7. windows程序快速启动的方式:WIN键+R

    WIN键+R是windows快速启动程序的一种方式,一般能独立运行的程序都能以这种方式启动.如notepad.calc.explorer等程序. 在命令行方式下explorer加上不同的参数,会得到不 ...

  8. Linux CentOS 7 安装配置vsftp

    学习Linux时间不长,首次安装了vsftp,按照网上的各种帖子尝试配置,不过都没打到预期,不是被拒绝连接,就是连接超时,总之就是各种问题啊.当然了,不是别人配置的不对,而是自己不是太懂Linux,选 ...

  9. 网络损伤仪WANsim的功能与型号

    网络损伤仪简介 WANsim网络损伤仪是一款可以模拟真实的广域网状况的设备.它可以通过简单的数据填写模拟出时延.带宽抖动.丢包.乱序.误码.报文重复等网络状况. 大多数公司在进行产品测试时,只关注了应 ...

  10. 01.泛型Generic

    1. 基本了解 1.1 什么是泛型? 字面意思:不确定的类型 泛型常用:泛型方法,泛型类,泛型接口,泛型委托 1.2 泛型 T(熟悉) T 的作用,其实就是一个通用的容器,制造它的人开始不指定它是用来 ...