引子:为什么要有操作系统

1,操作系统位于底层硬件与应用程序之间的一层

2,工作方式:向下管理硬件,向上提供接口

一,什么是进程

进程就是一个程序在一个个数据集上的一次动态执行过程。进程一般由程序,数据集,进程控制块三部分组成。

程序:用来描述进程要完成哪些功能以及如何完成。

数据集:是程序在执行过程中所需要使用的资源

进程控制块:用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用他来控制和管理进程,他是系统感知进程存在的唯一标志。

举例:

想象一位有一手好厨艺的计算机科学家正在为他的女儿烘制生日蛋糕。他有做生日蛋糕的食谱,厨房里有所需的原料:面粉、鸡蛋、糖、香草汁等。在这个比喻中,做蛋糕的食谱就是程序(即用适当形式描述的算法)计算机科学家就是处理器(cpu),而做蛋糕的各种原料就是输入数据。进程就是厨师阅读食谱、取来各种原料以及烘制蛋糕等一系列动作的总和。现在假设计算机科学家的儿子哭着跑了进来,说他的头被一只蜜蜂蛰了。计算机科学家就记录下他照着食谱做到哪儿了(保存进程的当前状态),然后拿出一本急救手册,按照其中的指示处理蛰伤。这里,我们看到处理机从一个进程(做蛋糕)切换到另一个高优先级的进程(实施医疗救治),每个进程拥有各自的程序(食谱和急救手册)。当蜜蜂蛰伤处理完之后,这位计算机科学家又回来做蛋糕,从他
离开时的那一步继续做下去。

二,什么是线程

线程的出现时为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干益阳市的缺陷,使到进程内并发称为可能。

假设,一个文本程序,需要接受键盘输入,将内容显示在屏幕上,还需要保存信息到硬盘中。若只有一个进程,势必造成同一时间只能干一样事的尴尬(当保存时,就不能通过键盘输入内容)。若有多个进程,每个进程负责一个任务,进程A负责接收键盘输入的任务,进程B负责将内容显示在屏幕上的任务,进程C负责保存内容到硬盘中的任务。这里进程A,B,C间的协作涉及到了进程通信问题,而且有共同都需要拥有的东西——-文本内容,不停的切换造成性能上的损失。若有一种机制,可以使任务A,B,C共享资源,这样上下文切换所需要保存和恢复的内容就少了,同时又可以减少通信所带来的性能损耗,那就好了。是的,这种机制就是线程。
线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能。线程没有自己的系统资源。

进程:最小的资源管理单位,可以理解成容器,而线程是容器里的东西

线程:最小的可执行单位,真正执行的是线程

三,进程与线程的关系

1,一个线程只能属于一个进程,而一个进程可以有多个线程,注意:创建一个进程,最少必须有一个线程。

2,资源分配给进程,同一进程的所有线程共享该进程的所有资源

3,CPU分给线程,真正在CPU上运行的是线程。

四,并行和并发

并行处理(Parallel Processing):

是计算机系统中能同时执行两个或更多个处理的一种计算方法。并行处理可同时工作于同一程序的不同方面。并行处理的主要目的是节省大型和复杂问题的解决时间。

一个进程:同一时间多个线程同时执行,基于有几个cpu,就是并行

并发处理(concurrency Processing):

指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机(cpu)上运行,但是,只能任一个时刻上只有一个程序在处理机(cpu)上运行

一个进程:多个线程轮流切换执行,就是并发

串行

从上到下一个一个执行,

五,同步与异步

在计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。

举个例子,打电话时就是同步通信,发短息时就是异步通信。

在python中,多线程由于GIL锁,导致同一时刻同一线程只能有一个被执行,所以没有并行,但是可用多进程来实现并行的效果

六,python并发之多线程

threading模块:

python中把所有与线程相关的操作,都封装成了threading接口,所有的操作都是通过threading模块来实现的

调用方式1:

 1 #调用方式1
 2 import threading
 3 import time
 4
 5 def look():
 6     print("看dog")  # 1
 7     time.sleep(3)  # t1遇到IO睡3秒 线程切换到t2
 8     print("看dog结束") # 3
 9 def walk():
10     print("开始walking") #2
11     time.sleep(5)   # t2遇到IO睡五秒  线程切换到t1
12     print("walking结束")   #4
13     print("程序运行时间:%s"%(time.time()-s)) #5
14 s=time.time()
15 t1 = threading.Thread(target=look) #创建t1对象
16 t2 = threading.Thread(target=walk)  #创建t2对象
17 t1.start()
18 t2.start()

调用方式2:继承threading类

import threading
import time
#调用方式2 ,继承threading类
class MyThread(threading.Thread): #继承threading模块下的Thread类def __init__(self,num):threading.Thread.__init__(self) #继承父类的init方法self.num = numdef run(self):  #重写父类的run方法print("running on number:%s"%self.num)time.sleep(3)print("结束")
t1 = MyThread(100)
t2 = MyThread(200)
t1.start()
print("ending")
t2.start()#执行结果
running on number:100
ending
running on number:200
结束
结束

Thread实例对象的方法  # isAlive(): 返回线程是否活动的。# getName(): 返回线程名。# setName(): 设置线程名。threading模块提供的一些方法:# threading.currentThread(): 返回当前的线程变量。# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。jion与setdamemon方法:jion:一个线程对象未执行完毕,会阻塞你的主线程setdamenmon:守护线程:程序直到不存在非守护线程是退出
# join():在子线程完成运行之前,这个子线程的父线程将一直被阻塞。# setDaemon(True):'''将线程声明为守护线程,必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起。当我们在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程 就分兵两路,分别运行,那么当主线程完成想退出时,会检验子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以 用setDaemon方法啦'''import threading
from time import ctime,sleep
import timedef Music(name):print ("Begin listening to {name}. {time}".format(name=name,time=ctime()))sleep(3)print("end listening {time}".format(time=ctime()))def Blog(title):print ("Begin recording the {title}. {time}".format(title=title,time=ctime()))sleep(5)print('end recording {time}'.format(time=ctime()))threads = []t1 = threading.Thread(target=Music,args=('FILL ME',))
t2 = threading.Thread(target=Blog,args=('',))threads.append(t1)
threads.append(t2)if __name__ == '__main__':#t2.setDaemon(True)for t in threads:#t.setDaemon(True) #注意:一定在start之前设置
        t.start()#t.join()#t1.join()#t2.join()    #  考虑这三种join位置下的结果?print ("all over %s" %ctime())

七,UIL全局解释器锁

GIL全局锁,只有cpython中有,别的解释器没有

计算密集型:一直在使用cup,计算密集型任务,python多线程并没有用

IO密集型:存在大量的IO操作,对于IO密集型任务,python 多线程是有意义的

八,同步锁(lock)

锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用release方法释放锁:

import time,threadingdef subnum():global num  #全局变量#num-=1#print("ok")#lock.acquire() #锁定开始,获取temp = numtime.sleep(0.0000001)num = temp - 1#lock.release()  #锁定结束,释放

num = 100
thread_list = []
lock = threading.Lock()  #创建一把锁for i in range(100):t = threading.Thread(target=subnum)t.start()thread_list.append(t)
for l in thread_list:l.join()print("result:",num)

九,死锁与递归锁

在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:

import threading
import timemutexA = threading.Lock()
mutexB = threading.Lock()class MyThread(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):self.fun1()self.fun2()def fun1(self):mutexA.acquire()  # 如果锁被占用,则阻塞在这里,等待锁的释放print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))mutexB.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))mutexB.release()mutexA.release()def fun2(self):mutexB.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))time.sleep(0.2)mutexA.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))mutexA.release()mutexB.release()if __name__ == "__main__":print("start---------------------------%s"%time.time())for i in range(0, 10):my_thread = MyThread()my_thread.start()

Rlock:

import threading
import time# mutexA = threading.Lock()
# mutexB = threading.Lock()
rlock = threading._RLock()class MyThread(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):self.fun1()self.fun2()def fun1(self):#mutexA.acquire()  # 如果锁被占用,则阻塞在这里,等待锁的释放
        rlock.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))#mutexB.acquire()
        rlock.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))#mutexB.release()
        rlock.release()#mutexA.release()
        rlock.release()def fun2(self):#mutexB.acquire()
        rlock.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))time.sleep(0.2)# mutexA.acquire()
        rlock.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))#mutexA.release()
        rlock.release()#mutexB.release()
        rlock.release()if __name__ == "__main__":print("start---------------------------%s"%time.time())for i in range(0, 10):my_thread = MyThread()my_thread.start()

十,event对象

event对象:默认False
用于两个线程通信的场景
event.wait 判断flag是否为False
event.set 把Flase改为True

线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其 他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就 会变得非常棘手。为了解决这些问题,我们需要使用threading库中的Event对象。 对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在 初始情况下,Event对象中的信号标志被设置为假。如果有线程等待一个Event对象, 而这个Event对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真,它将唤醒所有等待这个Event对象的线程。如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件, 继续执行

event.isSet():返回event的状态值;event.wait():如果 event.isSet()==False将阻塞线程;event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;event.clear():恢复event的状态值为False。

十一,队列(queue模块)

get与put方法:

'''创建一个“队列”对象import Queue
q = Queue.Queue(maxsize = 10)
Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数
maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。将一个值放入队列中
q.put(10)
调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;
第二个block为可选参数,默认为
1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,
put方法将引发Full异常。将一个值从队列中取出
q.get()
调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且
block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。'''

join与task_done方法:

'''
join() 阻塞进程,直到所有任务完成,需要配合另一个方法task_done。def join(self):with self.all_tasks_done:while self.unfinished_tasks:self.all_tasks_done.wait()task_done() 表示某个任务完成。每一条get语句后需要一条task_done。import queue
q = queue.Queue(5)
q.put(10)
q.put(20)
print(q.get())
q.task_done()
print(q.get())
q.task_done()q.join()print("ending!")
'''

先进先出,先进后出,优先级模式:

'''Python Queue模块有三种队列及构造函数: 1、Python Queue模块的FIFO队列先进先出。  class queue.Queue(maxsize)
2、LIFO类似于堆,即先进后出。           class queue.LifoQueue(maxsize)
3、还有一种是优先级队列级别越低越先出来。 class queue.PriorityQueue(maxsize) import queue#先进后出q=queue.LifoQueue()q.put(34)
q.put(56)
q.put(12)#优先级
q=queue.PriorityQueue()
q.put([5,100])
q.put([7,200])
q.put([3,"hello"])
q.put([4,{"name":"alex"}])while 1:data=q.get()print(data)'''

生产者消费者模型

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

这就像,在餐厅,厨师做好菜,不需要直接和客户交流,而是交给前台,而客户去饭菜也不需要不找厨师,直接去前台领取即可,这也是一个结耦的过程。

import time,random
import queue,threadingq = queue.Queue()def Producer(name):count = 0while count <10:print("making........")time.sleep(random.randrange(3))q.put(count)print('Producer %s has produced %s baozi..' %(name, count))count +=1#q.task_done()#q.join()print("ok......")
def Consumer(name):count = 0while count <10:time.sleep(random.randrange(4))if not q.empty():data = q.get()#q.task_done()#q.join()print(data)print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))else:print("-----no baozi anymore----")count +=1p1 = threading.Thread(target=Producer, args=('A',))
c1 = threading.Thread(target=Consumer, args=('B',))
# c2 = threading.Thread(target=Consumer, args=('C',))
# c3 = threading.Thread(target=Consumer, args=('D',))
p1.start()
c1.start()
# c2.start()
# c3.start()

  

转载于:https://www.cnblogs.com/gaoyuan111/p/6825346.html

python--------进程与线程相关推荐

  1. python进程和线程_Python进程与线程知识

    好程序员Python 培训分享进程与线程知识 , Python 开发语言现在已经是被大家非常看中的编程语言了,本篇文章给读者们分享一下 Python 进程与线程知识小结,本篇文章具有一定的参考借鉴价值 ...

  2. python进程和线程

    python 进程和线程 概念 GIL: 全局解释锁,解决了不同线程同时访问统一资源时,数据保护问题.python 虽然是多线程,但是因为GIL,实际上是是单线程,由CPU轮询,假线程.(一个线程运行 ...

  3. python进程与线程_Python进程与线程知识

    Python培训分享进程与线程知识,Python开发语言现在已经是被大家非常看中的编程语言了,本篇文章给读者们分享一下Python进程与线程知识小结,本篇文章具有一定的参考借鉴价值,感兴趣的小伙伴来了 ...

  4. python 进程,线程,协程篇

    python 进程,线程,协程篇 ssh 线程 进程 线程,进程区别 threading 模块,两种调用方式 python GIL全局解释器锁(Global Interpreter Lock) Joi ...

  5. Python进程和线程保姆式教学,1个台机子多只手干活的秘籍

    进程线程有多重要?刚开始学Python的时候你可能还没有感觉到,因为你写的代码从上到下执行一遍就可以了,但实际上这很初级,实际开发写项目的时候,为了充分利用电脑配置来加快程序进度,我们往往会用到多进程 ...

  6. Python进程、线程、协程详解

    进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...

  7. python进程、线程的学习心得

    什么是多线程竞争? 线程不是独立的,同一个进程里的线程,线程间的数据是共享的,多线程操作时,容易造成数据的混乱,线程不安全. 如何解决? 互斥锁. 好处:能够保证某段关键代码执行时,只有一个线程操作, ...

  8. python进程、线程、协程

    基本观点: 1.一个python进程一个GIL(全局锁),每个线程需要获取这个锁才能执行. 2.cpu密集型的程序,使用多进程. 3.IO密集型的程序,多线程可能会比多进程快. 4.多核cpu执行多进 ...

  9. python 进程和线程

    python中的进程.线程(threading.multiprocessing.Queue.subprocess) Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就 ...

  10. python 进程与线程(理论部分)

    一.理论部分 一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行): egon在一个时间段内有很多任务要做:python备课的 ...

最新文章

  1. socket不能bind请求的地址_socket通信原理
  2. JS数组去重方法小结
  3. SAP Cloud for Customer的inscreen_dataflow处理方式
  4. 从 vue-cli 源码中,我发现了27行读取 json 文件有趣的 npm 包
  5. MapReduce详解和WordCount模拟
  6. 开源GraphView的使用--数据统计
  7. PostgreSQL查询当前执行中SQL的执行计划——pg_show_plans
  8. 如何把一个数据库的数据copy到另外一个数据库
  9. 如何在 Mac 上查找和删除重复文件?
  10. 不是我吹,这款神仙 IDEA 插件你真没用过!
  11. GIS案例练习-----------第四天
  12. 微信小程序 this.data与this.setData
  13. 《信息系统项目管理师教程》目录
  14. PHP通过身份证号码获取性别、出生日期、年龄等信息
  15. android消息提示框大小,android Toast設置彈框大小
  16. 计算机常用的输出设备有什么作用,常用的多媒体输入输出设备有哪些,主要功能是什么...
  17. 【线程 锁】ExecutorService的submit方法使用
  18. 如何成为一名获得Adobe认证的专业人员?
  19. 签证者的武林秘笈(一)—-来自太傻的签证哲学
  20. 阿诺德给物体加描边_【C4DtoA 27】Arnold渲染器: Toon shader 1/3

热门文章

  1. golang new和make却别
  2. golang goroutine协程运行机制及使用详解
  3. Spring Cloud 微服务实战系列-Ribbon入门RestTemplate 介绍
  4. python函数格式化_Python通过format函数格式化显示值
  5. 预处理和typedef
  6. 问题:pom文件飘红, parent.relativePath
  7. 使用Express搭建Web服务器
  8. 微服务网关总结之 —— zuul
  9. disruptor模拟高速处理大规模订单类业务场景
  10. 新手学习嵌入式需要掌握的几点知识点