操作系统线程理论

mac2022-06-30  94

目录

操作系统线程理论 线程概念的引入背景 进程有了进程为什么要有线程线程的出现进程和线程的关系 大白话描述进程与线程threading模块 线程的创建多进程与多线程多线程实现socketserverThread类的其他方法线程的join方法守护线程

操作系统线程理论

线程概念的引入背景

进程

​ 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。

有了进程为什么要有线程

​ 进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上:

进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。

  如果这两个缺点理解比较困难的话,举个现实的例子也许你就清楚了:如果把我们上课的过程看成一个进程的话,那么我们要做的是耳朵听老师讲课,手上还要记笔记,脑子还要思考问题,这样才能高效的完成听课的任务。而如果只提供进程这个机制的话,上面这三件事将不能同时执行,同一时间只能做一件事,听的时候就不能记笔记,也不能用脑子思考,这是其一;如果老师在黑板上写演算过程,我们开始记笔记,而老师突然有一步推不下去了,阻塞住了,他在那边思考着,而我们呢,也不能干其他事,即使你想趁此时思考一下刚才没听懂的一个问题都不行,这是其二。

  现在你应该明白了进程的缺陷了,而解决的办法很简单,我们完全可以让听、写、思三个独立的过程,并行起来,这样很明显可以提高听课的效率。而实际的操作系统中,也同样引入了这种类似的机制——线程。

线程的出现

​ 60年代,在OS中能拥有资源和独立运行的基本单位是进程,然而随着计算机技术的发展,进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。

  因此在80年代,出现了能独立运行的基本单位——线程(Threads)。

  注意:进程是资源分配的最小单位,线程是CPU调度的最小单位.

     每一个进程中至少有一个线程。 

进程和线程的关系

线程与进程的区别可以归纳为以下4点:

  1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。

  2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

  3)调度和切换:线程上下文切换比进程上下文切换要快得多。

  4)在多线程操作系统中,进程不是一个可执行的实体。

大白话描述进程与线程

在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程,cpu真正的执行单位是线程. 在工厂中, 每个车间都有房子,而且每个车间默认就有一条流水线. 操作系统 ===> 工厂 进程 ===> 车间 线程 ===> 流水线 cpu ===> 电源 线程:操作系统调度的最小单位 进程:资源集合/资源单位(最小的内存分配单位) 线程运行 = 运行代码 进程运行 = 各种资源 + 线程 线程与进程的区别 线程==》单指代码的执行过程 进程==》资源的申请与销毁的过程 进程内存空间彼此隔离 同一个进程下的线程共享资源. 进程和线程的创建速度 进程需要申请资源开辟空间 慢 线程只是告诉操作系统一个执行方案 快

threading模块

线程的创建

# 第一种 from threading import Thread import time def func(name): print('线程 start') time.sleep(2) print('线程 end') if __name__ == '__main__': t = Thread(target=task) t.start() print('主进程') # 第二种 from threading import Thread import time # 进程等待所有线程结束才会结束 class Mythread(Thread): def run(self): print('子线程 start')45 time.sleep(5) print('子线程 end') t = Mythread() t.start() print('主线程')

多进程与多线程

pid的比较

from threading import Thread from multiprocessing import Process import os def work(): print('hello',os.getpid()) if __name__ == '__main__': #part1:在主进程下开启多个线程,每个线程都跟主进程的pid一样 t1=Thread(target=work) t2=Thread(target=work) t1.start() t2.start() print('主线程/主进程pid',os.getpid()) #part2:开多个进程,每个进程都有不同的pid p1=Process(target=work) p2=Process(target=work) p1.start() p2.start() print('主线程/主进程pid',os.getpid())

开启效率的较量

from threading import Thread from multiprocessing import Process import os def work(): print('hello') if __name__ == '__main__': #在主进程下开启线程 t=Thread(target=work) t.start() print('主线程/主进程') ''' 打印结果: hello 主线程/主进程 ''' #在主进程下开启子进程 t=Process(target=work) t.start() print('主线程/主进程') ''' 打印结果: 主线程/主进程 hello '''

内存数据的共享问题

from threading import Thread from multiprocessing import Process import os def work(): global n n=0 if __name__ == '__main__': # n=100 # p=Process(target=work) # p.start() # p.join() # print('主',n) #毫无疑问子进程p已经将自己的全局的n改成了0,但改的仅仅是它自己的,查看父进程的n仍然为100 n=1 t=Thread(target=work) t.start() t.join() print('主',n) #查看结果为0,因为同一进程内的线程之间共享进程内的数据 同一进程内的线程共享该进程的数据?

多线程实现socketserver

# server import socket from threading import Thread sk = socket.socket() sk.bind(('127.0.0.1', 8088)) sk.listen() def func(conn): while True: res = conn.recv(1024).decode('utf8') print(res) conn.send(res.upper().encode('utf8')) if __name__ == '__main__': while True: conn, addr = sk.accept() t = Thread(target=func,args=(conn,)) t.start() # client1 import socket sk = socket.socket() sk.connect(('127.0.0.1',8088)) while True: data = input('>>>') data = 'client1:'+data sk.send(data.encode('utf8')) res = sk.recv(1024).decode('utf8') print(res) # client2 import socket sk = socket.socket() sk.connect(('127.0.0.1',8088)) while True: data = input('>>>') data = 'client2:'+data sk.send(data.encode('utf8')) res = sk.recv(1024).decode('utf8') print(res)

Thread类的其他方法

Thread实例对象的方法 # isAlive(): 返回线程是否活动的。 # getName(): 返回线程名。 # setName(): 设置线程名。 threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。 from threading import Thread import threading from multiprocessing import Process import os def work(): import time time.sleep(3) print(threading.current_thread().getName()) if __name__ == '__main__': #在主进程下开启线程 t=Thread(target=work) t.start() print(threading.current_thread().getName()) print(threading.current_thread()) #主线程 print(threading.enumerate()) #连同主线程在内有两个运行的线程 print(threading.active_count()) print('主线程/主进程') ''' 打印结果: MainThread <_MainThread(MainThread, started 140735268892672)> [<_MainThread(MainThread, started 140735268892672)>, <Thread(Thread-1, started 123145307557888)>] 主线程/主进程 Thread-1 '''

线程的join方法

from threading import Thread import time def sayhi(name): time.sleep(2) print('%s say hello' %name) if __name__ == '__main__': t=Thread(target=sayhi,args=('egon',)) t.start() t.join() print('主线程') print(t.is_alive()) ''' egon say hello 主线程 False '''

守护线程

# 守护线程 守护的是进程的运行周期 from threading import Thread,enumerate,currentThread import time def task(): print('守护线程开始') print(currentThread()) time.sleep(5) print('守护线程结束') def task2(): print('子线程 start') time.sleep(3) print(currentThread()) print('子线程 end') if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task2) t1.daemon = True t1.start() t2.start() time.sleep(5) print(enumerate()) print('主') ''' 守护线程开始 <Thread(Thread-1, started daemon 1540)> 子线程 start <Thread(Thread-2, started 14464)> 子线程 end [<_MainThread(MainThread, started 14732)>, <Thread(Thread-1, started daemon 1540)>] 主 守护线程结束 '''

转载于:https://www.cnblogs.com/dadazunzhe/p/11543406.html

最新回复(0)