线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
1.地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
2.通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
3.调度和切换:线程上下文切换比进程上下文切换要快得多。
4.在多线程操作系统中,进程不是一个可执行的实体。
1.多线程共享一个进程的地址空间
2.线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用
3.若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。
4.在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(这一条并不适用于python)
from threading import Thread import time def test(name): time.sleep(2) print('%s say hello' %name) if __name__ == '__main__': t=Thread(target=test,args=('xie',)) t.start() print('主线程')函数方式
from threading import Thread import time class MyThread(Thread): def __init__(self,name): super().__init__() self.name=name def run(self): time.sleep(2) print('%s say hello' % self.name) if __name__ == '__main__': t = MyThread('xie') t.start() print('主线程')类方式
t.isAlive(): 返回线程是否活动的
t.getName(): 返回线程名
t.setName(): 设置线程名
threading.currentThread(): 返回当前的线程变量
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
随主线程运行完毕而停止并被回收。对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕。
from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------") # 输出依次: # 123 # 456 # main------- # end123 # end456守护线程
模拟100个人同时抢票的情况,在不加锁的情况下数据容易混乱的,就很有可能造成最后的数据与逻辑不符。
from threading import Thread import time def grab(): global n temp=n time.sleep(0.1) n=temp-1 if __name__ == '__main__': n=100 l=[] for i in range(100): t=Thread(target=grab) l.append(p) t.start() for t in l: t.join() print(n) #结果可能为99错误现象
我们需要加锁保证数据的安全,即把并行改成串行,保证同一时间内只有一个线程执行对数据的操作。threading与multiprocess类似,也有Lock。
from threading import Thread,Lock import time def grab(): global n lock.acquire() temp=n time.sleep(0.1) n=temp-1 lock.release() if __name__ == '__main__': lock=Lock() n=100 l=[] for i in range(100): t=Thread(target=grab) l.append(t) t.start() for t in l: t.join() print(n) # 结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全加锁
只要在服务端开设多线程来接收多个客户端的访问就能实现并发
import socket from threading import Thread from multiprocessing import Process server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) def talk(sock): while True: try: data = sock.recv(1024) if len(data) == 0: break print(data.decode('utf8')) sock.send(data + b'server端') except ConnectionResetError as e: print(e) break sock.close() while True: sock, addr = server.accept() print(addr) # 开设多进程或者多线程 t = Thread(target=talk, args=(sock,)) t.start()server端并发