本文是学习《Python核心编程》的学习笔记,介绍了Python中的全局解释器锁和常用的两个线程模块:thread, threading,并对比他们的优缺点和给出简单的列子。

全局解释器锁(GIL)

Python代码的执行都是有Python虚拟机进行控制的。当初设计Python的时候,考虑在主循环中只能有一个控制线程在执行,就像单核CPU进行多线程编程一样。

怎么做到这样控制的呢?就是这里的GIL来控制的,这个锁用来保证同时只有一个线程在运行。

执行方式:

这几个细节知识点:

当调用外部代码(C/C++扩展的内置函数)时, GIL会保持锁定,知道函数执行结束

对于面向I/O的Python例程,GIL会在I/O调用前被释放,从而允许其他线程在I/O执行期间运行

如果是针对计算密集型的操作代码,该线程整个时间片内更倾向于始终占有处理器和GIL。

所以,针对Python虚拟机单线程(GIL)的设计原因,只有线程在执行I/O密集型的应用,才能更好的发挥Python的并发性。

对比thread,threading

Python多个模块可以进行多线程编程,包括:thread,threading等。他们都可以用来创建和管理线程。

thread模块提供了基本的线程和锁定支持,而threading模块提供了更高级别,功能更全面的线程管理。

推荐使用更高级别的threading模块,下面是一个简单的对比:

特征要素

thread

threading

功能全面性

基本(偏底层)

全面,高级

守护进程

不支持

支持

线程同步原语

仅1个(Lock)

很多(Lock,Semaphore,Barrier...)

守护进程讲解

守护进程一般是一个等待客户端请求服务的服务器。如果没有客户端请求,守护进程一般是空闲的。一般把一个线程设置成守护进程,就表示这个线程是不重要的。所以进程退出时是不需要等待这个守护线程完成的。

但是原先的thread 模块是不区分守护或者非守护进程的,也就是说当主线程退出的时候,所有子线程都将终止,而不管他们是否仍在工作。如果你不想这种情况发生,那么就可以采用threading模块。整个Python程序(一般为主线程)将在所有非守护进程退出是才会退出。

设置守护进程,在线程启动之前设置:thread.daemon = True

多线程实践

threading实例

方式1:创建一个thread实例,传递它一个函数

import threading

from time import sleep, ctime

sleep_times = [4, 2]

def loop(threadNo, sleep_time):

print('Start loop', threadNo, 'at:', ctime())

sleep(sleep_time) #Sleep一段时间

print('loop', threadNo, 'done at:', ctime())

def main():

print('starting at:', ctime())

threads = []

threadIds = range(len(sleep_times))

for i in threadIds:

thread = threading.Thread(target=loop, args=(i,sleep_times[i]))

threads.append(thread)

for t in threads:

# 依次启动线程

t.start()

for t in threads:

# 等待所有线程完成

t.join() #将等待线程结束

print('all Done at :', ctime())

if __name__ == '__main__':

main()

方式2:派生Thread的子类,并创建子类的实例

import threading

from time import sleep, ctime

sleep_times = [4, 2]

class MyThread(threading.Thread):

def __init__(self, func, args, name=''):

threading.Thread.__init__(self)

self.func = func

self.name = name

self.args = args

def run(self):

self.func(*self.args)

def loop(threadNo, sleep_time):

print('Start loop', threadNo, 'at:', ctime())

sleep(sleep_time) # Sleep一段时间

print('loop', threadNo, 'done at:', ctime())

def main():

print('starting at:', ctime())

threads = [] # 用于存储所有线程实例的列表

threadIds = range(len(sleep_times))

for i in threadIds:

# 创建线程实例

thread = MyThread(loop, (i, sleep_times[i]))

threads.append(thread)

for t in threads:

# 依次启动线程

t.start()

for t in threads:

# 等待所有线程完成

t.join() # 将等待线程结束

print('all Done at :', ctime())

if __name__ == '__main__':

main()

thread实例

由于本人使用的python3.6,这个thread已经变成_thread

import _thread

from time import sleep, ctime

sleep_times = [4, 2]

def loop(threadNo, sleep_time, lock):

print('Start loop', threadNo, 'at:', ctime())

sleep(sleep_time) #Sleep一段时间

print('loop', threadNo, 'done at:', ctime())

lock.release() #释放锁

def main():

print('starting at:', ctime())

locks = []

threadIds = range(len(sleep_times))

for i in threadIds:

#通过调用_thread.allocate_lock获得锁对象

lock = _thread.allocate_lock()

#通过acquire()方法取得锁

lock.acquire()

locks.append(lock)

for i in threadIds:

# 依次启动线程

_thread.start_new_thread(loop, (i, sleep_times[i], locks[i]))

for i in threadIds:

# 如果当前的锁Lock没有释放的话,一直循环等待

while locks[i].locked():

pass

print('all Done at :', ctime())

if __name__ == '__main__':

main()

python3多线程编程_Python 3多线程编程学习笔记-基础篇相关推荐

  1. MySQL学习笔记-基础篇1

    MySQL 学习笔记–基础篇1 目录 MySQL 学习笔记--基础篇1 1. 数据库概述与MySQL安装 1.1 数据库概述 1.1.1 为什么要使用数据库 1.2 数据库与数据库管理系统 1.2.1 ...

  2. Redis学习笔记①基础篇_Redis快速入门

    若文章内容或图片失效,请留言反馈.部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 资料链接:https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA( ...

  3. MySQL学习笔记-基础篇2

    MySQL学习笔记-基础篇2 目录 MySQL学习笔记-基础篇2 8.子查询 8.1 需求分析与问题解决 8.1.1 实际问题 8.1.2 子查询的基本使用 8.1.3 子查询的分类 8.2 单行子查 ...

  4. 易语言学习笔记——基础篇

    易语言学习笔记20180710 一. 易语言的数据类型可以分为基本数据类型和特殊数据类型 1.     其中基本数据类型分为: ①   数值型 ②   逻辑型 ③   日期时间型 ④   文本型 ⑤  ...

  5. Python学习笔记——基础篇【第五周】——模块

    模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...

  6. java学习笔记-基础篇

    Java基础篇 1-12 常识 13 this关键字 14参数传递 16 继承 17 访问权限 28-31异常 1-12 常识 1.文件夹以列表展示,显示扩展名,在地址栏显示全路径 2.javac编译 ...

  7. extlink.php,ExtJs 学习笔记基础篇 Ext组件的使用_extjs

    昨天刚接触到Extjs,简单写了篇学习笔记,今天继续. 天介绍一下Ext中组件举几个简单的例子做说明.注意:文章内容有些摘自本人学习过程中看到的资料. Ext2.0对框架进行了非常大的重构,其中最重要 ...

  8. C++ 学习笔记----基础篇

    (一)类和抽象数据类型   1.通过类实现的接口(公有和私有)可实现信息隐藏.实现对数据的封装等: 2.抽象数据类型(ADT:Abstract Data Type):当一个数据类型仅暴露公有接口,而将 ...

  9. 扇贝编程python无法退款_扇贝编程python学习笔记-基础篇1

    我要成为一个勤奋努力上进的人 第一关 学习用时:15min 随堂测验+上机作业:10min 随堂作业正确率:4/5 1.尝试执行代码 import random menu = ['粉丝', '炒饭', ...

最新文章

  1. where引导的定语从句与状语从句区别
  2. json 序列化 java_Java JSON序列化杂谈
  3. 微软想将新版Edge浏览器引入Linux
  4. SpringBoot 2.x yml 文件中自定义参数解析对象
  5. 【心情】最近实在是太忙了,没有心情写东西!
  6. 实验八 java多线程操作_20182310实验八实验报告
  7. 单片机ADC采样算法----加权递推平均滤波法
  8. 4月23日云栖精选夜读:阿里AI新物种!设计机器人两年赶上资深员工水平
  9. 【网络基础】《TCP/IP详解》学习笔记6
  10. linux mysql skip_skip-grant-tables 修改linux的mysql忘记root密码
  11. linux修改dns地址的三种方法
  12. 如何用计算机术语写论文,计算机毕业论文结论怎么写?
  13. 根据四个特征点求解相机位姿
  14. 全球与中国云计算数据中心IT资产处置(ITAD)市场深度研究分析报告
  15. C++实现二叉树 前、中、后序遍历(递归与非递归)非递归实现过程最简洁版本
  16. c#.net连接access数据库
  17. STM32 自定义HID USB设备的实现
  18. error uploading crisocket: timed out waiting for the conditionswapoff -a # will turn off the swap
  19. 屏幕适配和百分比布局
  20. windows 向 iPad导入文件

热门文章

  1. oracle中 start with,Oracle中connect by...start with...的使用
  2. 调用第三方接口的几种请求方式
  3. 使用java向ftp上传多张图片_ftp免费空间,利用ftp工具定时连接ftp免费空间教程及java配置...
  4. 小程序如何调用php程序,微信小程序调用PHP后台接口 解析纯html文本
  5. 忽视大小写函数_使用率低但功能强大的6个Excel函数公式应用技巧解读!
  6. JavaScript 的 Date 方法的使用
  7. java 三级考试_java三级考试理论题
  8. Java 源码--Arrays
  9. ajax调用java程序,从微信小程序到鸿蒙JS开发-JS调用Java
  10. java线程安全例子_Java总结篇系列:Java多线程(三)