首页 > 编程 > Python > 正文

python3-多线程

2019-11-08 18:36:43
字体:
来源:转载
供稿:网友

注:这篇文章部分为廖雪峰py3教程:点我,本文使用python3.5

线程的使用场景:

python有GIL锁(global InterPReter lock),由于这个锁的存在,在任意给定时刻只有一个线程在执行。这里有一篇讲得稍微详细的文章:点击打开链接对于任意面向I/O的python程序,GIL会在I/O调用前释放,以允许其他线程在I/O执行的时候运行。所以来说,在I/O密集型的python程序要比计算密集型的程序能够更好的利用多线程

常用的methods

(1)thread模块不支持守护线程,守护线程表示这个线程不是重要的,进程退出时不需要等待这个线程执行完成。在python的另一个模块threading中支持守护线程。

(2)threading.current_thread().name:获取当前线程的名字

(3)线程实例.start():线程开始执行

(4)线程实例.join():等待目前正在执行的线程执行完毕

(5)线程实例.daemon = True:设置该线程为守护线程

例子一:

import timeimport threadingdef run_func():    print('[+]thread %s is running...' % threading.current_thread().name)    cnt = 0    while cnt < 5:        cnt += 1        print('thread %s >>> %s' % (threading.current_thread().name, cnt))        time.sleep(1)    print('thread %s ended' % threading.current_thread().name)if __name__ == '__main__':    print('thread %s is running..' % threading.current_thread().name)    t = threading.Thread(target=run_func, name='LoopThread')    t.start()    t.join()    print('[+]thread %s ended' % threading.current_thread().name)例子二:import threadingimport timedef func(slp):    name = threading.current_thread().name    print('[+]thread%s start at ' % name, time.ctime())    time.sleep(slp)    print('[+]thread%s end at ' % name, time.ctime())if __name__ == '__main__':    trds = list()    slps = [x*2 for in range(1, 5)]    for each in range(4):        trds.append(threading.Thread(target=func, args=(slps[each], )))    print('[+]main time start at', time.ctime())    for each in trds:        each.start()    for each in trds:        each.join()    print('[+]main time end at ', time.ctime())'''output:[+]main time start at Sun Feb  5 17:02:13 2017[+]threadThread-1 start at  Sun Feb  5 17:02:13 2017[+]threadThread-2 start at  Sun Feb  5 17:02:13 2017[+]threadThread-3 start at  Sun Feb  5 17:02:13 2017[+]threadThread-4 start at  Sun Feb  5 17:02:13 2017[+]threadThread-1 end at  Sun Feb  5 17:02:15 2017[+]threadThread-2 end at  Sun Feb  5 17:02:17 2017[+]threadThread-3 end at  Sun Feb  5 17:02:19 2017[+]threadThread-4 end at  Sun Feb  5 17:02:21 2017[+]main time end at  Sun Feb  5 17:02:21 2017'''

守护线程:

import threadingimport timedef func(output, sleeptime):    print('[+]start at', time.ctime())    print('%s' % threading.current_thread().name, output)    time.sleep(sleeptime)    print('[+]end at', time.ctime())if __name__ == '__main__':    sleeptime = 5    thr = threading.Thread(name='lrh', target=func, args=('test now...', sleeptime))    thr.daemon = True    thr.start()    '''#设置为守护线程后,程序执行完thr.start()后就开始退出,#由于执行了sleep(),输出是不会同时有start at 时间,end at 时间的 #output:[+]start at Thu Feb 16 17:40:07 2017'''

线程锁

进程之间的变量是拷贝的,而线程是共用变量,所有当多个线程存在时需要限制其他线程不能使用,仅某个线程可以使用,这就是线程锁,import threadingimport osimport timeimport randombalance = 0lock = threading.Lock()def run_func(n):    global balance    balance = balance + n    balance = balance - ndef run_thread(n):    for each in range(10000):        lock.acquire()        try:            run_func(n)        except Exception as error:            print(error)        finally:            lock.release()t1 = threading.Thread(target=run_thread, args=(5000099,))t2 = threading.Thread(target=run_thread, args=(100000,))t1.start()t2.start()t1.join()t2.join()print(balance)多个线程执行lock.acquire()时,只有一个线程能成功的获取锁,其他线程只能等待,所以一定要记得释放锁此外,在python中可以使用上下文管理,即使用with语句。

多核cpu:

import threadingimport multiprocessingdef loop():    x = 0    while True:        x = x ^ 1for in range(multiprocessing.cpu_count()):    t = threading.Thread(target=loop)    t.start()由于GIL全局锁把所有的线程的执行上了锁,多线程在python中只能交替的运行,即使100个线程跑在100核cpu上,也只能用到一个核

ThreadLocal,解决多线程局部变量的传递问题

由于线程之间的全局变量是共用的,所以对于一个线程来说,使用局部变量是最好的,避免影响其他线程之间的变量,那么就会有一个问题,局部变量在传递起来就会比较麻烦一个可行的思路是使用线程名字作为key,value来存放待传递变量python给我们提供了更加方便的做法,使用ThreadLocalimport threadinglocalSet = threading.local()def func_run():    std = localSet.student    print('Hello, %s (in %s)' % (std, threading.current_thread().name))def thread_run(name):    localSet.student = name    func_run()if __name__ == '__main__':    t1 = threading.Thread(target=thread_run, args=('lrh', ), name='Thread-A')    t2 = threading.Thread(target=thread_run, args=('kch',), name='Thread-B')    t1.start()    t2.start()    t1.join()    t2.join()


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表