python3-多线程

注:这篇文章部分为廖雪峰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 time
import threading


def  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 threading
import time


def  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* 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 threading
import time


def 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 threading
import os
import time
import random


balance =  0
lock = threading.Lock()


def  run_func(n):
    global balance
    balance = balance + n
    balance = balance - n


def  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 threading
import multiprocessing


def  loop():
    x =  0
    while True:
        x = x ^  1


for in  range(multiprocessing.cpu_count()):
    t = threading.Thread( target=loop)
    t.start()

由于GIL全局锁把所有的线程的执行上了锁,多线程在python中只能交替的运行,即使100个线程跑在100核cpu上,也只能用到一个核


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

由于线程之间的全局变量是共用的,所以对于一个线程来说,使用局部变量是最好的,避免影响其他线程之间的变量,那么就会有一个问题,局部变量在传递起来就会比较麻烦

一个可行的思路是使用线程名字作为key,value来存放待传递变量

python给我们提供了更加方便的做法,使用ThreadLocal

import threading


localSet = 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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值