*:first-child {
margin-top: 0 !important;
}

body>*:last-child {
margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
font-size: inherit;
}

h1 {
font-size: 28px;
color: #000;
}

h2 {
font-size: 24px;
border-bottom: 1px solid #ccc;
color: #000;
}

h3 {
font-size: 18px;
}

h4 {
font-size: 16px;
}

h5 {
font-size: 14px;
}

h6 {
color: #777;
font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
color: #4183C4;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
padding-left: 30px;
}

ul li > :first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}

dl {
padding: 0;
}

dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}

dl dt:first-child {
padding: 0;
}

dl dt>:first-child {
margin-top: 0px;
}

dl dt>:last-child {
margin-bottom: 0px;
}

dl dd {
margin: 0 0 15px;
padding: 0 15px;
}

dl dd>:first-child {
margin-top: 0px;
}

dl dd>:last-child {
margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}

pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}

pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}

pre code, pre tt {
background-color: transparent;
border: none;
}

kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}

blockquote>:first-child {
margin-top: 0px;
}

blockquote>:last-child {
margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}

/* TABLES
=============================================================================*/

table th {
font-weight: bold;
}

table th, table td {
border: 1px solid #ccc;
padding: 6px 13px;
}

table tr {
border-top: 1px solid #ccc;
background-color: #fff;
}

table tr:nth-child(2n) {
background-color: #f8f8f8;
}

/* IMAGES
=============================================================================*/

img {
max-width: 100%
}
-->

Python 线程(threading) 进程(multiprocessing)

最近学了两个python库,一个负责管理线程,一个负责管理进程,原来一直写的都 是些单线程的程序,虽然web也关于并发和多涉及到线程,但都是框架管理的,学习>过后发现了解线程和进程对python的web开发也有一定帮助。下面先谈谈这对python对线程和进程的支持再谈谈对这两个库的应用。

python对线程的支持并不是非常好,所以你可以在很多文章上批评python的多线程的弊端,但是为什么python对多线程支持不好呢,为什么其他语言比如 C、java、c#静态语言没有这个弊端呢。

首先我们要知道python是一种解释性语言,每段代码都需要解释器编译运行,解释器有很多种最主要的是CPython,其他还有IronPythonJython,官方的是CPython解释器,我们一般说对多线程支持不好的就是说的CPython解释器(用的人最多就省略成python解释器),python解释器为什么对多线程支持不好呢,是因为GIL的存在,当然这个存在就是因为这门语言的的特性产生的。

GIL是什么呢,下面是官方的解释

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

就是GIL是python的互斥锁,简单的理解就是代码会锁住python解释器。理解代码的锁定是什么必须要先了解什么是多线程

多线程表示一个主线程,多个子线程,主线程是程序执行时系统自动给你申请的一个线程,而子线程我们可以理解为一个代码块,我们可以充分利用硬件的支持比如说多核,让一个CPU执行主线程,其他CPU执行子线程,通过操作系统的虚拟内存技术让所有线程共享相同代码空间达到提高代码效率的作用,我们可以通俗的把一个进程比作一辆火车,车厢头为主线程,每节车厢为子线程,只要你车厢(子线程)越多,你运的货物也越多,但是也要考虑硬件的方面,

了解完多线程是什么我们就可以解释GIL对多核CPU工作性能的影响了,在单核CPU里面,主线程在释放GIL的时候,把CPU让给子线程,子线程代码块得到GIL,然后执行,这样就能充分利用CPU,这个GIL对单核性能的发挥没有影响,能得到100%的利用,但是在多核的的时候就有问题了,假如主线程的代码一直需要解释器来执行, 比如说下面

    GIL.acquire()
try:
while True:
do_something()
finally:
GIL.release()

主线程代码对GIL的锁定和解开只间隔很小的一个系统时间,子线程在其他CPU核心得到GIL解开后CPU的调度命令后才能被唤醒,但是当唤醒后,主线程的代码又锁了GIL,然后只能等待主线程下次调度命令,但是到了切换时间又切换回去到待调整状态,一直处于唤醒,等待的恶性循环,多核的功能完全没有发挥出来而且还比单核更加差,所以python因为GIL的存在对密集型的线程支持不佳,但是假如主线程是在执行想web这样等待用户输入,而不是每分每秒都在使用解释器执行代码,多线程的优势就能发挥出来。

解决方案

GIL作为解释器的一个Bug一样的存在,我们也有一定的解决方法,开线程,和用Ctype绕过解释器是我们一般的解决方法,你想了解更多可以看这个 接下来主要解绍用multiprocessing来绕过多线程的瓶颈

线程锁和进程锁

为了实现线程安全,我们也要借助锁的存在,我们先用下面的代码来验证一下多线程对于线程安全的问题。我们声明一个线程锁 threading.Lock(),
class Counter(object):
def __init__(self, start=0):
self.lock = threading.Lock()
self.value = start def increment(self):
logging.debug('Waiting for lock') self.lock.acquire()
try:
if self.value < 8:
time.sleep(2) # 模拟负载
logging.debug('Acquired lock')
self.value = self.value + 1 finally:
self.lock.release()
def worker(c):
for i in range(2):
pause = random.random()
logging.debug('Sleeping %0.02f', pause)
time.sleep(pause)
c.increment()
logging.debug('Done')
counter = Counter()
for i in range(20):
t = threading.Thread(target=worker,args=(counter,))
t.start()
main_thread = threading.currentThread()
for t in threading.enumerate():
if t is not main_thread:
t.join() # 保护线程
logging.debug('Counter:%d', counter.value) #得到value值

我们运行之后得到counter.value值为8,这很好理解因为我们限制了它的大小小于8时才自增1,但是如果我们把锁去掉呢,我们把self.lock.acquire()self.lock.release()都注释掉,得到的结果却是一个21,而且每次运行的结果都可能不一样,由于线程在实现自增的时候有一定的时间(time.sleep(2)),所以当多个进程执行的时候当他们从堆栈上取到counter.value值都为7时,这时候他们都满足 counter.value小于8,所以都执行了自增,在系统负载2秒之间(time.sleep(2))有多少个线程执行就会逃过我们给他的限制,这样就造成了线程的不安全,但是我们给他加上锁之后,无论开多少个线程,最终结果都是8。在python里面我们线程锁和进程锁我们可以看做是同一种东西。

ps:当同一线程相互争夺锁时,失败的会进出线程队列等待锁解开。

线程进程工作方式

单行

单行主要通过锁来实现,线程通过锁threading.Lock()对象创造锁,进程通过multiprocessing.Lock()对象创建进程锁,单行操作一般都是对共享数据修改的一种保护。

并行

并行操作是一般是对数据的一种共享,一般不对公共数据涉及修改,我们可以创造很多线程和进程一起并行操作,也可以限制线程和进程的并行数量,两种方式选择主要是判断代码类型是I/O密集还是线程密集型的。如何限制并行数量我们可以通过threading.Semaphore(sizenum)(进程为multiprocessing.Semaphore(sizenum))我们可以控制对共享的线程数量。进程提供了一个进程池的类型(multiprocessing.Pool),我们可以创建一个维护了一定程的进程池,但是他同时并行的数量并没有控制,只是帮我们创建了这个进程池,每个进程并不是只执行一个任务,可能执行多个方法通过一个进程.

单行混合并行

单行和并行混合我们可以通过在代码中设置锁来实现,当然python给我们提供了两种对象来实现单行和并行的控制,线程的是threading.Event()threading.Condition(),进程的是multiprocessing.Event()multiprocessing.Condition() 两种对象都是提供了一种命令指令,但是Event对象可以用来判断命令是否下达而做出相应的反应,而Condition对象更倾向于当命令下达后才执行并行的操作。

线程和进程通信方式

当我们想让线程和进程共同执行一些固定的任务,我们就需要线程和进程之间能够通信,线程和进程通信我们使用队列(Queue),进程和线程的Queue有点差异,就是进程Queue传递的对象必须pickle化,而且为了能够使用join()(保护进程)task_done(通知任务完成),我们一般使用JoinableQueue 代替Queue在进程中。

Queue对象之间通过putget通信,我们把任务put上去,Queue自动分配给当前的线程或进程, 这样就能实现对任务的流水作业话。

引用

12/26/2015 10:50:21 PM GIL维基资料

GIL博文

Python 线程(threading) 进程(multiprocessing)的更多相关文章

  1. Python线程,进程,携程,I/O同步,异步

    只有本人能看懂的-Python线程,进程,携程,I/O同步,异步 举个栗子: 我想get三个url,先用普通的for循环 import requests from multiprocessing im ...

  2. Python 线程和进程和协程总结

    Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...

  3. Python 线程、进程和协程

    python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费时间,所以我们直接学习threading 就可以了. ...

  4. python基础-第九篇-9.1初了解Python线程、进程、协程

    了解相关概念之前,我们先来看一张图 进程: 优点:同时利用多个cpu,能够同时进行多个操作 缺点:耗费资源(重新开辟内存空间) 线程: 优点:共享内存,IO操作时候,创造并发操作 缺点:抢占资源 通过 ...

  5. Python 线程(threading)

    Python 的thread模块是比较底层的模块,Python的threading模块是对thread做了一些包装,可以更加方便的 被使用; 1. 使用threading 模块 # 示例一: 单线程执 ...

  6. python线程、进程和协程

    链接:http://www.jb51.net/article/88825.htm 引言 解释器环境:python3.5.1 我们都知道python网络编程的两大必学模块socket和socketser ...

  7. python 线程、进程与协程

    一.什么是线程?什么是进程? 第一,进程是一个实体.每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region).数据区域(data region)和堆栈(stack regio ...

  8. python 线程,进程与协程

    引言 线程 创建普通多线程 线程锁 互斥锁 信号量 事件 条件锁 定时器 全局解释器锁 队列 Queue:先进先出队列 LifoQueue:后进先出队列 PriorityQueue:优先级队列 deq ...

  9. python 线程与进程

    线程和进程简介 应用程序和进程以及线程的关系? 一个应用程序里可以有多个进程,一个进程里可以有多个线程 最原始的计算机是如何运行的? CPU是什么?为什么要使用多个CPU? 为什么要使用多线程? 为什 ...

随机推荐

  1. 连接Oracle11g数据库时遇到无监听,网络适配器无法建立等问题的一些解决办法

    最近在用Java做一个学生成绩管理系统,打算用Oracle数据库.由于原先没接触过Oracle,所以安装完数据库后,连接数据库时遇到各种问题,网上搜索解决方案还是没有解决时,又重新安装了几次.终于在前 ...

  2. 修改UITextfield的Placeholder字体的颜色

    - (void)viewDidLoad { [super viewDidLoad]; self.title=@"修改UITextField的placeholder字体颜色"; UI ...

  3. js 计算两个日期之间的月数

    //返回两个日期相差的月数 function MonthsBetw(date1, date2) { //用-分成数组 date1 = date1.split("-"); date2 ...

  4. redis基础操作

    /** * redis的Java客户端Jedis测试验证 * * @author */ public class Test { /** * 非切片客户端链接 */ private Jedis jedi ...

  5. hdu Big Number 求一个数的位数

    Problem Description In many applications very large integers numbers are required. Some of these app ...

  6. HDU 5044 离线LCA算法

    昨天写了HDU 3966 ,本来这道题是很好解得,结果我想用离线LCA 耍一把,结果发现离线LCA 没理解透,错了好多遍,终得AC ,这题比起 HDU 3966要简单,因为他不用动态查询.但是我还是错 ...

  7. PAT 64.Complete Binary Search Tree

    题目链接: http://pat.zju.edu.cn/contests/pat-a-practise/1064 思路分析: 1)先对数组排好序. 2)采用中序遍历的方式,将排好序的元素逐个插入在完全 ...

  8. ORA-942 SP2-0611

    环境:oracle 11.2.04 问题描述: 在使用hr用户启用set autot trace时报错 set">HR@test>set autot trace; Error O ...

  9. php正则验证手机号码

    protected function checkphone(){ if(preg_match("/^1[34578]\d{9}$/", $phone)){ return false ...

  10. JavaWeb学习笔记--Servlet代码集

    目录: 登录系统提交表单数据打开PDFCookieURL传递参数URL重写跟踪会话使用HttpSession对象跟踪会话Servlet间协作过滤器Filter 登录系统 <!DOCTYPE HT ...