关于Python的进程线程协程之thread模块

简介

thread模块为python下的多线程处理,提供了产生线程的基本方法和锁方法的,支持建议不要和threading模块同时使用。


关于线程锁

所谓的锁,即基本的同步数据锁对象lock object,也称原语锁,简单锁,互斥锁,二值信号量,作用是同步数据,防止产生脏数据


thread模块方法和锁对象的描述

  1. start_new_thread(function,args,kwargs=None) 产生一个新线程对象,在新线程中调用指定参数(args和可选的kwargs)的函数function
  2. allocte_lock() 分配一个LockType类型的锁对象
  3. exit() 让线程退出
  4. LockType类型锁对象方法
  5. acquire(wait=None) 尝试获取锁对象
  6. locked() 线程对象如果获取了锁对象返回True,否则返回False
  7. release() 释放锁

实例一:


未使用thread模块的实例

解释器将变量以及函数读入内存之后,执行main函数,方法依次调用,顺序执行

from time import sleep,ctime
"""
the process that no mode of thread 
"""



def loop0():
    '''function for  sleep 4s '''
    print "start loop0 at: ",ctime()
    sleep(4)
    print "end loop0 at: ",ctime()

def loop1():
    '''function for sleep 2s '''
    print "start loop1 at: ", ctime()
    sleep(2)
    print "end loop1 at: ", ctime()


def main():
    '''function of main'''
    print "process start at: ".upper(),ctime()
    loop0()
    loop1()
    print "process end at: ".upper(),ctime()


if __name__ == '__main__':
    main()

执行结果如下:

PROCESS START AT:  Tue Apr 25 16:48:04 2017
start loop0 at:  Tue Apr 25 16:48:04 2017
end loop0 at:  Tue Apr 25 16:48:08 2017
start loop1 at:  Tue Apr 25 16:48:08 2017
end loop1 at:  Tue Apr 25 16:48:10 2017
PROCESS END AT:  Tue Apr 25 16:48:10 2017

实例二:


使用thread模块的实例

#_*_utf-8_*_
import thread
from time import sleep,ctime

"""
the process that have mode of thread 
"""


def loop0():
    '''A function for sleep 4s '''
    print "start loop0 at: ",ctime()
    sleep(4)
    print "end loop0 at: ",ctime()

def loop1():
    '''A function for sleep 2s '''
    print "start loop1 at: ", ctime()
    sleep(2)
    print "end loop1 at: ", ctime()

def main():
    '''A function of main'''
    print "process start at: ".upper(),ctime()
    thread.start_new_thread(loop0,())
    thread.start_new_thread(loop1,())
    sleep(6)
    print "process end at: ".upper(),ctime()

if __name__ == '__main__':
    main()

执行结果如下:

PROCESS START AT:  Tue Apr 25 16:50:38 2017
start loop0 at:  Tue Apr 25 16:50:38 2017
start loop1 at:  Tue Apr 25 16:50:38 2017
end loop1 at:  Tue Apr 25 16:50:40 2017
end loop0 at:  Tue Apr 25 16:50:42 2017
PROCESS END AT:  Tue Apr 25 16:50:44 2017

ps:如果在main函数里去掉sleep(6),那么,在主线程里将运行函数loop1和loop2的两个线程产生后,主线程将继续运行,不管产生的两个新线程是否执行完成,但此时系统一定会报错,如下:

PROCESS START AT:  Tue Apr 25 16:56:36 2017
PROCESS END AT:  Tue Apr 25 16:56:36 2017
Unhandled exception in thread started by 
sys.excepthook is missing
lost sys.stderr
Unhandled exception in thread started by 
sys.excepthook is missing
lost sys.stderr

为了避免以上情况(即当主线程退出时,所有的子线程不论是否还在工作,都会被强行退出)的出现,由此引入了守护线程,比thread更高级的threading模块支持守护线程,不过我们可以用后文讲到的锁机制来模拟守护线程的作用作为弥补


线程锁:thread模块的锁方法

针对python的GIL,python的多线程处理在cpu性能欠佳的情况下往往会产生脏数据,比如多个线程在同时修改共享数据,例如全局变量,此时可能会产生数据不同步,因为python2.7内部默认每一个线程执行100条cpu指令(差不多这么多条),执行完了我切换到另一个线程执行100条指令,假设在某个场景下,主线程产生两个线程A,B,同时修改全局变量i=0,让它增一,A线程刚拿到i的初始值准备修改,而并未开始修改,此时cpu的100条指令执行完,此时保存现场,切换到B线程执行,它获取到i的初始值依旧未变,即跟A拿到的一样,那么,照这样执行下去,最后A,B修改后返回的i的值就会是相同的即i=1,此时,就产生了数据不同步,脏数据产生。这也是锁出现的原因。

实例三:

thread模块:未设置锁的多线程实例

#_*_utf-8_*_
import thread

"""
the process that have mode of thread and no Lock 
"""

count = 0


def loop(arg):
    '''function for modify the global value
     count and sleep 2s 
    '''
    global count
    count += 1
    sleep(1)
    print "count of modified in loop %s is :"%arg,count

def main():
    '''function of main'''
    print "begin count = ".upper,count

    for i in range(50):
        thread.start_new_thread(loop,(i,))

    sleep(10)
    print "final count = ".upper,count


if __name__ == '__main__':
    main()

运行结果如下:

<built-in method upper of str object at 0x00000000034DD870> 0
count of modified in loop 0 is : count of modified in loop 2 is :1 
 2count of modified in loop 1 is :
 count of modified in loop 3 is :3 
 4count of modified in loop 4 is :
  count of modified in loop 6 is :6count of modified in loop 5 is : 
 7count of modified in loop 8 is :7

8
count of modified in loop 7 is :count of modified in loop 9 is : <built-in method upper of str object at 0x00000000034EF300> 10 10
10

······此处省略n行······

count of modified in loop 44 is :count of modified in loop 41 is :41
Process finished with exit code 0

ps:*脏数据的产生*:由于产生的线程未设置互斥锁,导致全局变量count最终修改结果产生误差,并且所有的线程在输出的时候都在抢占输出中断导致输出乱序

实例四:

thread模块:设置锁的多线程实例

#_*_utf-8_*_
import thread

"""
the process that have mode of thread and  Lock 
"""

count = 0
#global value
num = 50
#number of threads
Lock_Pool = []
#object of locks

def loop(arg,Lp):
    '''function for modify the global value
     count 
    '''
    global count
    count += 1
    print "count of modified in loop %s is :"%arg,count
    Lp.release()


def Thread_End(arg):
    for i in range(arg):
        while Lock_Pool[i].locked :pass

def LockPool():
'''A function that produce intantiation of Lock 
'''
    for i in range(num):
        lock = thread.allocate()
        lock.acquire()
        Lock_Pool.append(lock)


def main():
    '''A function of main:
        produce Lock pool
        start every thread
        wait every thread finish in main until the all end        
    '''


    LockPool()
    #produce Locks
    print "begin count = ".upper,count

    for i in range(num):
        thread.start_new_thread(loop,(i,Lock_Pool[i]))

    Thread_End(num)
    #wait all threads end
    print "final count = ".upper,count


if __name__ == '__main__':
    main()

其中的Thread_End函数就是本文实例二提到的模拟守护线程的功能,通过判断每个线程的锁是否还在获取状态来阻塞主线程,用这样的低级的一个一个判断的方法来弥补thread模块不支持守护线程的缺陷

def Thread_End(arg):
    for i in range(arg):
        while Lock_Pool[i].locked :pass

关于线程同步:其中函数LockPool的定义是为了,实现线程们的同步执行,避免有的线程还在获取锁,有的线程已经运行结束了

def LockPool():
'''A function that produce intantiation of Lock 
'''
    for i in range(num):
        lock = thread.allocate()
        lock.acquire()
        Lock_Pool.append(lock)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JaysenLeo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值