多线程编程

一、线程和进程


1.进程
计算机的程序只是在磁盘上可执行的二进制(或其他类型)文件。只有把它们加载到内存中并被操作系统调用,才拥有其生命周期。进程则是一个执行中的程序。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。操作系统管理其上所有进程的执行,并为这些进程合理的分配时间。进程也可以派生(fork或spwan)新的进程来执行其他任务,不过因为每个新进程也都拥有自己的内存和数据栈等,所以只能采用进程间通信(IPC)的方式共享信息。
2.线程
线程与进程类似,不过它们是在同一个进程下执行的,并共享上下文。可以将它们认为是在一个主进程或“主线程”中并行运行的一些“迷你进程”。
线程包括开始、执行顺序和结束三个部分。它有一个指令指针,用于记录当前运行的上下文。当其他线程运行时,它可以被抢占(中断)和临时挂起(也成睡眠)—-这种做法叫让步。
一个进程中的各个线程与主线程共享同一个数据空间,因为相比于独立的进程而言,线程间的信息共享和通信更加容易。线程一般是以并发方式执行的,正是由于这种并发和数据共享机制,使得多任务间的协调成为可能。当然在单核CPU系统中,因为真正的并发是不可能的,所以线程的执行实际上这样规划的:整个进程的执行过程中,每个线程执行它自己特定的任务,在必要时和其他线程进行结果通信。
当然,这种共享并不是没有风险。如果两个或多个线程访问同一片数据,由于数据访问顺序不同,可能导致结果不一致。这种情况通常称为竞态条件。幸运的是,大多数线程库都有一些同步原语,以允许线程管理器控制执行和访问。

二、Python的threading模块


python提供了多个模块来支持多线程编程,包括:thread、threading、Queue模块等。程序是可以使用thread和threading模块来创建与管理线程。thread模块提供了基本的线程和锁定支持;而threading模块提供了更高级别、功能更全面的线程管理。

1.thread模块


#派生一个新线程,使用给定的args和可选的kwargs来执行function
start_new_thread(function,args,kwargs=None)
#分配 LockType锁对象
allocate_lock()
#给线程退出指令
exit()

LockType锁对象的方法:

#尝试获取锁对象
acquire(wait=None)
#如果获取了锁对象则返回True,反之False
locked()
#释放锁
release()

示例1

#!/usr/bin/python
import thread
from time import sleep,ctime

def loop0():
    print 'start loop 0 at:',ctime()
    sleep(4)
    print 'loop 0 done at:',ctime()

def loop1():
    print 'start loop 1 at:',ctime()
    sleep(2)
    print 'loop 1 done at:',ctime()

def main():
    print 'starting at:',ctime()
    thread.start_new_thread(loop0,())
    thread.start_new_thread(loop1,())
    sleep(6)
    print 'all DONE at:',ctime()

if __name__=='__main__':
   main()
结果:   
starting at: Tue Dec 19 15:34:08 2017
start loop 1 at: Tue Dec 19 15:34:08 2017
start loop 0 at: Tue Dec 19 15:34:08 2017
loop 1 done at: Tue Dec 19 15:34:10 2017
loop 0 done at: Tue Dec 19 15:34:12 2017
all DONE at: Tue Dec 19 15:34:14 2017

示例2(线程和锁)

#!/usr/bin/python
import thread
from time import sleep,ctime
loops = [4,2]

def loop(nloop,nsec,lock):
    print 'start loop',nloop,'at:',ctime()
    sleep(nsec)
    print 'loop %s done at:%s' % (nloop,ctime())
    lock.release()

def main():
     print 'starting at:',ctime()
     locks = []
     nloops = range(len(loops))

     for i in nloops:
          lock = thread.allocate_lock()
          lock.acquire()
          locks.append(lock)

     for i in nloops:
          thread.start_new_thread(loop,(i,loops[i],locks[i]))
     for i in nloops:
          while locks[i].locked():pass
     print 'all  DONE at:',ctime()
if __name__=='__main__':
   main()

2.threading模块

对  象                  
Thread                         #表示一个执行线程对象
Lock                           #锁原语对象
RLock                          #可重入锁对象,使单一线程可以(再次)获得已持有的锁(递归锁)
Condition                      #条件变量对象,使得一个线程等待另一个线程满足特定的"条件",比如改变状态或某个数据值
Event                          #条件变量的通用版本,任意数量的线程在等待某个事件的发生,在该事件发生后所有线程将被激活。
Semaphore                      #为线程间共享的有限资源提供了一个"计数器",如果没有可用资源时会被阻塞。
BoundedSemaphore               #与Semaphore相似,不过它不允许超过初始值
Timer                          #与Thread类似,不过它要在运行前等待一段时间
Barrier                        #创建一个"障碍",必须到达指定数量的线程后才可以继续。         

与thread比较,thread不支持守护线程,当主线程退出时,所有子线程,都将终止,而threading支持守护进程,其工作方式为:守护线程一般是一个等待客户端请求服务的服务器。如果没有客户端请求,守护线程就是空闲,如果把一个线程设置为守护线程,就表示这个线程是不重要的,进程退出时不需要等待这个线程执行完毕。

2.1 thread类

Thread 对象的属性和方法
属性
name                               #线程名
ident                              #线程的标识符
daemon                             #布尔标志,表示这个进程是否是守护进程
方法
__init__(group=None,target=None    #实例化一个线程对象,需要有一个可调用的target,以及其参数args       
,name=None,args=(),kwargs={}       #或kwargs。可选参数name或group参数,不过后者还未实现。此外,       
,verbose=None,daemon=None)         #verbose,标志也是可接受的。
start()                            #开始执行该进程
run()                              #定义线程功能的方法
join(timeout=None)                 #直至启动的线程终止之前一直挂起,除非给出了timeout,否则一直阻塞。
getName()                          #返回线程名
setName(name)                      #设置线程名
isAlivel/is_alive()                #布尔标志,表示这个线程是否存活。
isDaemon()                         #如果是守护线程,返回True,反之False
setDaemon(daemonic)                #把线程的守护标志设置成布尔值daemonic(必须在线程start()之前调用)         

示例(1)threading

#!/usr/bin/python
import threading
from time import sleep,ctime
loops = [4,2]

def loop(nloop,nsec):
    print 'start loop',nloop,'at:',ctime()
    sleep(nsec)
    print 'loop %s done at:%s' % (nloop,ctime())

def main():
     print 'starting at:',ctime()
     threads = []
     nloops = range(len(loops))

     for i in nloops:
         t = threading.Thread(target=loop,args=(i,loops[i]))
         threads.append(t)

     for i in nloops:
          threads[i].start()             #start threads
     for i in nloops:
          threads[i].join()              #wait for all
     print 'all  DONE at:',ctime()       #threads to finish
if __name__=='__main__':
   main()
结果:
starting at: Tue Dec 19 16:46:33 2017
start loop 0 at: Tue Dec 19 16:46:33 2017
start loop 1 at: Tue Dec 19 16:46:33 2017
loop 1 done at:Tue Dec 19 16:46:35 2017
loop 0 done at:Tue Dec 19 16:46:37 2017
all  DONE at: Tue Dec 19 16:46:37 2017

示例(2)创建Thread的实例

#!/usr/bin/python
import threading
from time import sleep,ctime
loops = [4,2]

class ThreadFunc(object):
      def __init__(self,func,args,name=''):
          self.name = name
          self.func = func
          self.args = args

      def __call__(self):
          self.func(*self.args)

def loop(nloop,nsec):
     print 'start loop',nloop,'at:',ctime()
     sleep(nsec)
     print 'loop %s done at:%s' % (nloop,ctime())

def main():
     print 'starting at:',ctime()
     threads = []
     nloops = range(len(loops))

     for i in nloops:                     #create all threads

         t = threading.Thread(target=ThreadFunc(loop,(i,loops[i]),loop.__name__))
         threads.append(t)

     for i in nloops:
          threads[i].start()             #start threads
     for i in nloops:
          threads[i].join()              #wait for all
     print 'all  DONE at:',ctime()       #threads to finish
if __name__=='__main__':
   main()
结果:
starting at: Tue Dec 19 17:08:51 2017
start loop 0 at: Tue Dec 19 17:08:51 2017
start loop 1 at: Tue Dec 19 17:08:51 2017
loop 1 done at:Tue Dec 19 17:08:53 2017
loop 0 done at:Tue Dec 19 17:08:55 2017
all  DONE at: Tue Dec 19 17:08:55 2017   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值