- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
前言
假设有一批小文件,每个文件都可以通过 mysql load 的方式导入数据库,请问如何操作可以取
得较小的时间和资源消耗?
关于这个需求,我们自然会想到各种并发实现方式,比如多进程和多线程。由于众所周知的多进
程切换的高昂代价以及在某些场合下需要考虑多进程之间的协调和通信,如果情非得已,恐怕很
少会使用到多进程。然而在本文讨论的 python 世界中,多线程可能也不是一个好的选择。详见
下文论述。
线程模型
我们知道操作系统的任务调度是基于内核调度实体(KSE,Kernel Scheduling Entity),所以线
程的实现也是基于内核调度实体,也就是通过跟内核调度实体绑定实现自身的调度。根据线程与
内核实体的对应关系上的区别,线程的实现模型大致可以分为两大类:内核级线程和用户级线
程。
- 内核级线程模型
线程与内核线程 KSE 是一对一(1 : 1)的映射模型,也就是每一个用户线程绑定一个实际的内
核线程,而线程的调度则完全交付给操作系统内核去做,应用程序对线程的创建、终止以及同步
都基于内核提供的系统调用来完成,大部分编程语言的线程库 (比如 Java 的 java.lang.
Thread、C++ 的 std::thread 等等) 都属于内核级线程模型。这种模型的优势和劣势同样明显:
优势是实现简单,直接借助操作系统内核的线程以及调度器,所以 CPU 可以快速切换调度线程,
于是多个线程可以同时运行,因此相较于用户级线程模型它真正做到了并行处理;但它的劣势
是,由于直接借助了操作系统内核来创建、销毁和以及多个线程之间的上下文切换和调度,因此
资源成本大幅上涨,且对性能影响很大。
- 用户级线程模型
线程与内核线程 KSE 是多对一(N : 1)的映射模型,多个用户线程的一般从属于单个进程并且
多线程的调度是由用户自己的线程库来完成,线程的创建、销毁以及多线程之间的协调等操作都
是由用户自己的线程库来负责而无须借助系统调用来实现。许多语言实现的协程库 基本上都属于
这种方式(比如 python 的 gevent)。由于线程调度是在用户层面完成的,避免了系统调用和
CPU 在用户态和内核态之间切换的开销,因此对系统资源的消耗会小很多,然而该模型有个问
题:假设在某个用户进程上的某个用户线程因为一个阻塞调用(比如 I/O 阻塞)而被 CPU 给中
断(抢占式调度)了,整个进程将被挂起。因此,该模型并不能做到真正意义上的并发。
python 线程
我们广泛使用的 python 是基于 CPython 实现,然而由于 CPython 的内存管理不是线程安全
的,于是引入了一个全局解释锁(Global Interpreter Lock)来保障 Python 的线程安全。正是
因为 GIL 的存在,每个线程执行前都需要获取锁,从而导致多线程的并发性大大削弱,完全无法
发挥多核的优势。同时 python 的线程切换是基于字节码指令的条数,因此对于 I/O 密集型计算
密集型任务勉强还有用武之地,然而对于计算密集型任务,多线程切换的开销将使多线程成为鸡
肋,执行效率反而不如单线程。以下是一个验证例子:
顺序执行的单线程 (single_thread.py)
#! /usr/bin/python
from threading import Thread
import time
def my_counter():
i = 0
for _ in range(100000000):
i = i + 1
return True
def main():
thread_array = {}
start_time = time.time()
for tid in range(2):
t = Thread(target=my_counter)
t.start()
t.join()
end_time = time.time()
print(Total time: {}.format(end_time - start_time))
if __name__ == __main__:
main()
同时执行的两个并发线程 (multi_thread.py)
#! /usr/bin/python
from threading import Thread
import time
def my_counter(
原创力文档


文档评论(0)