线程是一个基本的 CPU 执行单元。它必须依托于进程存活。一个线程是一个execution context(执行上下文),即一个 CPU 执行时所需要的一串指令
因作用不同划分为不同的类型:
GIL只在CPython中才有,而在其他解释器PyPy和Jython中是没有GIL的。
由于 GIL 锁存在,Python 里一个进程永远只能同时执行一个线程(拿到 GIL 的线程才能执行),这就是为什么在多核CPU上,Python 的多线程效率并不高的根本原因
Python提供两个模块进行多线程的操作,分别是thread和threading,前者是比较低级的模块,用于更底层的操作,一般应用级别的开发不常用。
threading.Thread()
import threading
def run(n):
print("current task:", n)
if __name__ == "__main__":
t1 = threading.Thread(target=run, args=("thread 1",))
t2 = threading.Thread(target=run, args=("thread 2",))
t1.start()
t2.start()
import threading
class MyThread(threading.Thread):
def __init__(self, n):
super(MyThread, self).__init__() # 重构run函数必须要写
self.n = n
def run(self):
print("current task:", self.n)
if __name__ == "__main__":
t1 = MyThread("thread 1")
t2 = MyThread("thread 2")
t1.start() #start之后运行run方法
t2.start()
Join函数是将该线程加入到主线程中,
依次执行每个join的线程,执行完毕后继续往下执行,不会同时执行。
主线程结束后,子线程还在运行,join函数使得主线程等到子线程结束时才退出。
import threading
def count(n):
while n > 0:
n -= 1
if __name__ == "__main__":
t1 = threading.Thread(target=count, args=("100000",))
t2 = threading.Thread(target=count, args=("100000",))
t1.start()
t2.start()
# 将 t1 和 t2 加入到主线程中
t1.join()
t2.join()
线程之间数据共享的。当多个线程对某一个共享数据进行操作时,就需要考虑到线程安全问题。threading模块中定义了Lock 类,提供了互斥锁的功能来保证多线程情况下数据的正确性。
#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire([timeout])
#释放
mutex.release()
可选参数timeout, 如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理。
import threading
import time
num = 0
mutex = threading.Lock()
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire(1):
num = num + 1
msg = self.name + ‘: num value is ‘ + str(num)
print(msg)
mutex.release()
if __name__ == ‘__main__‘:
for i in range(5):
t = MyThread()
t.start()
满足在同一线程中多次请求同一资源的需求。Python 提供了可重入锁(RLock)。
RLock内部维护着一个Lock和一个counter变量,counter 记录了 acquire 的次数,从而使得资源可以被多次 require。直到一个线程所有的 acquire 都被 release,其他的线程才能获得资源。
#创建 RLock
mutex = threading.RLock()
class MyThread(threading.Thread):
def run(self):
if mutex.acquire(1):
print("thread " + self.name + " get mutex")
time.sleep(1)
mutex.acquire()
mutex.release()
mutex.release()
如果希望主线程执行完毕之后,不管子线程是否执行完毕都随着主线程一起结束。我们可以使用setDaemon(bool)函数,它跟join函数是相反的。它的作用是设置子线程是否随主线程一起结束,必须在start() 之前调用,默认为False
class TimeLimited(Thread): #class中的两个函数是必须的
def __init__(self):
Thread.__init__(self)
def run(self):
func(params)
t = TimeLimited()
t.setDaemon(True) #这个用户线程必须设置在start()前面
t.start()
t.join(timeout=time_limited)
if t.is_alive():
raise Exception(‘连接超时‘)
规定函数在多少秒后执行某个操作
import threading
def func1(a):
print(‘Do something‘)
a+=1
print(a)
print(‘当前线程数为{}‘.format(threading.activeCount()))
if a>5:
return
t=threading.Timer(5,func1,(a,))
t.start()
原文:https://www.cnblogs.com/qian-shan/p/12596134.html