python 多线程

python 多线程

 

python threading模块提供线程相关操作。

线程是应用程序工作的最小单元。

1、线程是什么机理工作的?

    一个py程序可以看做一个主线程, 主线程里可以创建多个子线程。

    py程序从上到下执行完毕后,主线程即执行完毕。

    中间主线程如需等待子线程的返回值会等子线程,否则各自执行。另一种情况是子线程中有等待,那么主线程也不会等子线程。

    机理:通俗的讲计算机中只有一根大的指针(可能会和存储用的分开),这根指针是在内存中用到,调拨程序指令(可以理解为寻址)。

            比如同时开了是个子进程,并且是同一个对象开的(即要求同时并行),指针是忙碌在各个子进程之间,先将A1子进程中的a1指令执行后,调到A2子进程的a2指令。所以会看到这样的例子,注意时间戳有细小不同。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
  
def show(arg):
    time.sleep(1)
    print 'thread'+str(arg)
    print time.ctime()
    print time.time()
  
for i in range(10):
    t = threading.Thread(target=show, args=(id(i),))
    t.start()
  
print 'main thread stop'

>>> 
main thread stop
>>> thread8301716thread8301764thread8301728thread8301740thread8301776thread8301704thread8301788thread8301752thread8301692thread8301680









Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016Thu Dec 01 08:27:40 2016









1480552060.61480552060.611480552060.621480552060.631480552060.641480552060.641480552060.651480552060.661480552060.671480552060.67

  

再举一个例子,如果子进程准备就绪,而主进程还在跑,现在是各自执行吗?还是等待主进程执行后才会开始子进程。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
  
def show(arg):
    time.sleep(2)
    print 'thread'+str(arg)
    print time.ctime()
    print time.time()
  
for i in range(10):
    t = threading.Thread(target=show, args=(id(i),))
    t.start()
    
print "main thread sleep"
slep = 5
for i in range(slep):
    time.sleep(1)
    print "has slp %ss"%i

a=5
a=a+100
print a
print 'main thread stop'

>>> 
main thread sleep
has slp 0s
thread9481436thread9481412thread9481424thread9481388thread9481376thread9481364thread9481328thread9481340thread9481352thread9481400









Thu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016has slp 1sThu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016Thu Dec 01 09:19:44 2016










1480555184.311480555184.311480555184.321480555184.331480555184.331480555184.341480555184.351480555184.361480555184.361480555184.37









has slp 2s
has slp 3s
has slp 4s
105
main thread stop
>>> 

  谁都不会等谁,按照时间进行。

 还有这样的例子,验证到底在子进程真的是指针在来回跳动吗?

import threading
import time
  
def show(arg):
    time.sleep(2)
    print '2-----thread'+str(arg)
    time.sleep(2)
    print "3----",time.ctime()
    time.sleep(2)
    print "4--------",time.time()
def deng(arg):
    time.sleep(2)
    arg = arg*1000000
    time.sleep(2)
    print "3------%s"%arg
    time.sleep(2)
    print "4-----+++++++++"
def qwe(arg):
    time.sleep(2)
    print "2-------qwe"
    time.sleep(2)
    print "qweqwe"
    time.sleep(2)
    print "4-----zzzzzzzzzzzzzzzzzz"
a = [show,deng,qwe]
for i in range(3):
    t = threading.Thread(target=a[i], args=(id(i),))
    t.start()
    
'''print "main thread sleep"
slep = 5
for i in range(slep):
    time.sleep(1)
    print "has slp %ss"%i

a=5
a=a+100
print a'''
print 'main thread stop'

>>> 
main thread stop
>>> 2-----thread90882202-------qwe

3------9088208000000
3----qweqwe 
Thu Dec 01 10:13:14 2016
4-----+++++++++
4-----zzzzzzzzzzzzzzzzzz4--------
 1480558396.93

  可以看到几个函数中的第二部都在(基本同一时刻)执行(指针在几个函数中转换),然后都在sleep,如果有一个sleep时间过长,其余两个线程会继续执行不会等待。这就证明指针不会在一个线程中一直执行,而是会一执行在各个子线程中执行程序。

 

join的理解:在当前线程让指针加入一个在本线程内的操作时间,比如join(2),就是在这个线程中再多执行两秒后才能跳转到另外线程中。

                可以算作主线程将指针放置在子线程中等待,所有等待时间都是计算在主线程之内。

                这里介绍一个编程技巧,适用场景为多部设备一起执行任务时可以让子线程的任务都执行完,然后执行主线程的任务。

                多线程任务技巧

                http://www.cnblogs.com/lx63blog/articles/6248943.html

2、线程锁的作用

    不加锁的效果

#! /usr/bin/env python

import threading
import time
gl = 1
def f1():
    global gl
    gl = gl+1
    print "f1 out ",gl

def f2():
    global gl
    gl = gl+1
    print "f2 out ",gl
tl =[f1,f2]
for i in tl:
    
    t = threading.Thread(target=i)
    t.start()
time.sleep(3)
print "main end"

========================= RESTART: C:/Python27/rl.py =========================
f1 out f2 out   33

main end
>>> 
View Code

产生了脏数据。
    加了线程锁的效果

#! /usr/bin/env python

import threading
import time
#from weapon.ap import FuncTimer

lock = threading.RLock()
gl = 1
def f1():
    lock.acquire()
    global gl
    gl = gl+1
    print "f1 out ",gl
    lock.release()
def f2():
    lock.acquire()
    global gl
    gl = gl+1
    print "f2 out ",gl
    lock.release()
#ft = FuncTimer()
#@ft.functimer
def prp():
    tl =[f1,f2]

    for i in tl:
        
        t = threading.Thread(target=i)
        t.start()
    time.sleep(3)
    print "main end"
prp()


>>> 
========================= RESTART: C:/Python27/rl.py =========================
f1 out  2
f2 out  3
main end
cust time  3
>>> 
View Code

 3、生产者消费者模型

import queue

模型:管状存取模型

意义:1、为IO操作用户排队

       2、在服务器性能允许的情况下,可以节省时间,因为在cpu调度指针未到queue时,线程可以一直加入直到queue上限。当指针调度到queue时可以一次全部执行,而这个操作对用户是感知不到时间变慢。

 

posted on 2016-12-01 10:21  lexn  阅读(180)  评论(0编辑  收藏  举报

导航