通过继承的方式,实现线程:
import time
from threading import Thread
class MyThread(Thread):
def __init__(self, args):
super().__init__() #执行父类中的__init__()
self.args = args
def run(self):
time.sleep(2)
print(self.args)
t = MyThread(10)
t.start()
检测线程确实是在同一个进程中运行的(pid比较)
import time,os
from threading import Thread
#多线程并发
def func(n):
time.sleep(2)
print('子线程%d:%d'%(n,os.getpid()))
print('主线程:',os.getpid())
for i in range(10):
t = Thread(target=func,args=(i,))
t.start()
输出:
内存数据共享问题
同一个进程之内,多个线程之间的数据是共享的。
import time,os
from threading import Thread
#多线程并发
def func(n):
global g
g = 10
print(g,os.getpid())
g = 100
t_list = []
for i in range(5):
t = Thread(target=func,args=(i,))
t.start()
t_list.append(t)
for j in t_list:
j.join()
print(g)
输出:
全局解释锁(GIL)
在Cpython解释器下的python程序,在同一时间,多个线程中只能有一个线程被CPU执行。
当运行高CPU使用的代码(计算类)的时候,多线程确实不占优势,但一般情况下,我们运行的代码是高I/O的,所以,多线程还是有用的。
加了GIL的代码,同一时刻只有一个线程能访问CPU,锁的是线程
,这是Cpython解释器的特性,Jpython没有GIL。(面试)
在多线程环境中,Python虚拟机按以下方式执行
- 设置GIL;
- 切换到一个线程去执行;
- 运行指定数量的字节码指令或者线程主动让出控制;
- 把县城设置为睡眠状态;
- 解锁GIL;
- 重复上面的步骤
在调用外部代码(C/C++扩展函数)的时候,GIL将会被锁定,知道这个函数结束为止(由于在这期间没有Python的字节码被运行,所以不会做线程切换),编写扩展的程序员可以主动解锁GIL。
多线程效率
import time
from threading import Thread
from multiprocessing import Process
def func(n):
n + 1
if __name__ == '__main__':
t_list = []
start = time.time()
for i in range(100):
t = Thread(target=func,args=(i,))
t.start()
t_list.append(t)
for t in t_list:
t.join()
t1 = time.time() - start
t_list = []
start = time.time()
for i in range(100):
t = Process(target=func,args=(i,))
t.start()
t_list.append(t)
for t in t_list:
t.join()
t2 = time.time() - start
print(t1,t2)
多线程socket server
client端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
msg = sk.recv(1024).decode('utf-8')
print(msg)
inp = input('>>>').encode('utf-8')
sk.send(inp)
sk.close()
server端
import socket
from threading import Thread
def chat(conn):
conn.send(b'hello')
msg = conn.recv(1024).decode('utf-8')
print(msg)
conn.close()
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
while True:
conn,addr = sk.accept()
Thread(target=chat,args=(conn,)).start()
sk.close()
线程中一些其他的方法
threading.current_thread()
当前线程的所有信息
threading.get_ident()
当前线程的线程号
threading.active_count()
当前有多少个线程
threading.enumerate()
当前所有的线程
import threading,time
def nihao(n):
time.sleep(1)
print(n, threading.current_thread(), threading.get_ident())
for i in range(10):
threading.Thread(target=nihao, args=(1,)).start()
print(threading.active_count())
print(threading.current_thread())
print(threading.enumerate())
输出: