Python通过两个标准库(thread, threading)提供了对多线程的支持

thread模块

thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python3 中不能再使用”thread” 模块。为了兼容性,Python3 将 thread 重命名为 “_thread”。

import time
import thread
def runner(arg):
for i in range(6):
print str(i)+':'+arg
time.sleep(1)
#结束当前线程
thread.exit_thread()  #等同于thread.exit()
#启动一个线程,第一个参数为函数名,
#第二个参数为一个tuple类型,是传给函数的参数
thread.start_new_thread(runner, ('hello world',))   #等同于thread.start_new(runner, ('hello world'))
#创建一个锁,锁用于线程同步,通常控制对共享资源的访问
lock = thread.allocate_lock()  #等同于thread.allocate()
num = 0
#获得锁,成功返回True,失败返回False
if lock.acquire():
num += 1
#释放锁
lock.release()
#thread模块提供的线程都将在主线程结束后同时结束,因此将主线程延迟结束
time.sleep(10)
print 'num:'+str(num)


threading.Thread类的常用方法

1.在自己的线程类的__ init__里调用threading.Thread.__init__(self,name=threadname),threadname为线程的名字。

2.run(),通常需要重写,编写代码实现做需要的功能。

3.getName(),获得线程对象名称。

4.setName(),设置线程对象名称。

5.start(),启动线程。

6.join([timeout]),等待另一线程结束后再运行。

7.setDaemon(bool),设置子线程是否随主线程一起结束,必须在start()之前调用。默认为False。

8.isDaemon(),判断线程是否随主线程一起结束。

9.isAlive(),检查线程是否在运行中。

要想创建一个线程对象,只要继承类threading.Thread,然后在__ init__里边调用threading.Thread.__init__()方法即可。重写run()方法,将要实现的功能放到此方法中即可。

class runner(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
self.thread_stop = False
def run(self):
while not self.thread_stop:
print str(self.name)+':'+'hello world'
time.sleep(1)
def stop(self):
self.thread_stop = True
def test():
t = runner('thread')
t.start()
time.sleep(10)
t.stop()
if __name__ == '__main__':
test()


线程同步(锁)

最简单的同步机制就是锁。锁对象由threading.RLock类创建。线程可以使用锁的acquire()方法获得锁,这样锁就进入locked状态。每次只有一个线程可以获得锁。如果当另一个线程试图获得这个锁的时候,就会被系统变为blocked状态,直到那个拥有锁的线程调用锁的release()方法来释放锁,这样锁就会进入unlocked状态。blocked状态的线程就会收到一个通知,并有权利获得锁。

如果多个线程处于blocked状态,所有线程都会先解除blocked状态,然后系统选择一个线程来获得锁,其他的线程继续blocked。python的threading module是在建立在thread module基础之上的一个module,在thread module中,python提供了用户级的线程同步工具Lock对象。

而在threading module中,python又提供了Lock对象的变种: RLock对象。RLock对象内部维护着一个Lock对象,它是一种可重入的对象。对于Lock对象而言,如果一个线程连续两次进行acquire操作,那么由于第一次acquire之后没有release,第二次acquire将挂起线程。这会导致Lock对象永远不会release,使得线程死锁。

RLock对象允许一个线程多次对其进行acquire操作,因为在其内部通过一个counter变量维护着线程acquire的次数。而且每一次的acquire操作必须有一个release操作与之对应,在所有的release操作完成之后,别的线程才能申请该RLock对象。

我们把修改共享数据的代码称为临界区。必须将所有临界区都封闭在同一个锁对象的acquire和release之间。

import time
import threading
num=0
lock = threading.RLock()
class runner(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
global num
while True:
if num >= 6: break
if lock.acquire():
print "Thread(%s) locked, Number: %d" % (self.name, num)
time.sleep(1)
lock.release()
print "Thread(%s) released, Number: %d" % (self.name, num)
time.sleep(1)
num += 1
def test():
t1 = runner('thread1')
t2 = runner('thread2')
t1.start()
t2.start()
if __name__== '__main__':
test()


Python thread实现多线程

#-*- encoding: gb2312 -*-
import string, threading, time
def thread_main(a):
global count, mutex
# 获得线程名
threadname = threading.currentThread().getName()
for x in xrange(0, int(a)):
# 取得锁
mutex.acquire()
count = count + 1
# 释放锁
mutex.release()
print threadname, x, count
time.sleep(1)
def main(num):
global count, mutex
threads = []
count = 1
# 创建一个锁
mutex = threading.Lock()
# 先创建线程对象
for x in xrange(0, num):
threads.append(threading.Thread(target=thread_main, args=(10,)))
# 启动所有线程
for t in threads:
t.start()
# 主线程中等待所有子线程退出
for t in threads:
t.join()
if __name__ == '__main__':
num = 4
# 创建4个线程
main(4)


Python threading实现多线程

#-*- encoding: gb2312 -*-
import threading
import time
class Test(threading.Thread):
def __init__(self, num):
threading.Thread.__init__(self)
self._run_num = num
def run(self):
global count, mutex
threadname = threading.currentThread().getName()
for x in xrange(0, int(self._run_num)):
mutex.acquire()
count = count + 1
mutex.release()
print threadname, x, count
time.sleep(1)
if __name__ == '__main__':
global count, mutex
threads = []
num = 4
count = 1
# 创建锁
mutex = threading.Lock()
# 创建线程对象
for x in xrange(0, num):
threads.append(Test(10))
# 启动线程
for t in threads:
t.start()
# 等待子线程结束
for t in threads:
t.join()