多线程创建

def target():
    print 'current threading: %s is running' % threading.current_thread().name
    time.sleep(1)
    print 'current threading: %s is ended' % threading.current_thread().name

print 'current threading: %s is running' % threading.current_thread().name
t = threading.Thread(target=target)
t.setDaemon(True)
t.start()
t.join()
print 'current threading: %s is ended' % threading.current_thread().name
  • t.start()
    启动线程

  • t.join()
    阻塞当前线程,即使当前线程已经结束,也不会退出。上例中,thread-1结束后主线程才会结束。
    如果不加join语句,主线程不会等待子线程结束后再退出,而是立即退出,但并不会杀死子线程。

  • t.setDaemon(True)
    设置这个之后,如果不加join,那么主线程结束后会立即退出,并立即杀死子线程。
    可以使用join(int)等待一段时间,那么主线程会等待一段时间再退出。

线程锁

lock = threading.Lock()

在需要的时候acquire(),使用后通过release()释放。

lock.acquire()
try:
    a += 3
finally:
    lock.release()

ThreadLocal

线程局部变量,Flask基于此原理。

local = threading.local()
def func(name):
    local.name = name
    print "%s in %s" % (local.name, threading.current_thread().name)

t1 = threading.Thread(target=func, args=('xiaoming',))
t2 = threading.Thread(target=func, args=('xiaohong',))
t1.start()
t1.join()
t2.start()
t2.join()

map实现多线程

urls = ['http://www.baidu.com','http://www.sina.com','http://www.qq.com']
results=map(urllib2.urlopen,urls)

map函数负责将线程分给不同的CPU。

python中,有两个标准库包含map函数,分别是multiprocessing和multiprocessing.dummy。
区别:multiprocessing作用于进程,dummy作用于线程。

import urllib2
from multiprocessing.dummy import Pool as ThreadPool

urls = ['http://www.baidu.com','http://www.sina.com','http://www.qq.com']

pool = ThreadPool()

results = pool.map(urllib2.urlopen,urls)
print results
pool.close()
pool.join()

print 'main ended'
  • pool = ThreadPool()
    创建线程池,默认值为CPU的核心数。可以自己手动指定,该数值并非越大越好,因为切换线程时会很消耗资源。

  • result = pool.map(urllib2.urlopen, urls)
    将不同的url传递给不同的线程,并把执行结果返回到result中。

python多线程缺陷

python中存在一个GIL,全局解释器锁,该锁的存在保证同一时间只有一个线程执行任务,也就是说,python的多线程并非真正的并发,而是交替执行。

参考资料

  • https://segmentfault.com/a/1190000000414339
  • http://python.jobbole.com/85050/
  • http://zhuoqiang.me/python-thread-gil-and-ctypes.html