python--进程/线程

进程/线程

1 进程

操作系统进程切换:

1 出现IO操作:

2 固定时间:

 

2 进程定义 (资源管理单位)---(容器)

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

实现并发过程

进程是相互独立的。

 

3 线程(最小执行单位)

线程的出现是为了降低上下文切换的消耗,提供系统的并发性,并突破一个进程只能干一样的缺陷,使到进程内并发成为可能。

 

4 进程与线程的关系

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配

和调度的基本单位,是操作系统结构的基础

线程则是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位

进程与线程的关系:

(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

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

(3)CPU分给线程,即真正在CPU上运行的是线程

 

5 并行和并发

并行处理(Parallel Processing)

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

并发处理(concurrency Processing)

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

并发的关键是你有处理多个任务的能力,不一定要同时。并行的关键是你有同时处理多个任务的能力,所以说,并行是并发的子集

注意:

Python败笔多线程:由于GIL,导致同一时刻,同一进程只能有一个线程被运行。多进程可以并行,多线程不能并行。

 

6 同步与异步

同步:在计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去

异步:是指进程不需要一直等待下去,而是继续执行面的操作,不管其他进程的状态,当有消息返回时系统会通知进程进行处理

 

7 Threading模块

 Thread类执行创建:

import threading
import time

def listen():
    print("listen to the music")
    time.sleep(3)
    print("listne stop")

def write():
    print("writing blog")
    time.sleep(5)
    print("writing stop")

t1=threading.Thread(target=listen) #生成一条线程
t2=threading.Thread(target=write) #生成第二条线程
t1.start() #启动线程
t2.start()
print("ending") #主线程



执行效果:
listen to the music
writing blog
ending
listne stop
writing stop

 

Thread类继承式创建:

import threading
import time
class Mythread(threading.Thread):
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num=num
    def run(self):
        print("running on number:%s"%self.num)
        time.sleep(3)
t1=Mythread(56)
t2=Mythread(73)
t1.start()
t2.start()
print("ending")



执行结果:
running on number:56
running on number:73
ending

  

Thread类的实例方法:  

 Join()

t.join() : 线程对象t未执行完,会阻塞你的主线程。跟子线程没有关系

import threading
import time
from time import ctime,sleep

def Music(name):
    print("Begin listening to {name}".format(name=name,time=ctime()))
    sleep(3)
    print("end listenting{time}".format(time=ctime()))
def Blog(title):
    print("Begin recording the {title}".format(title=title,time=ctime ()))
    sleep(5)
    print("end recording the {time}".format(time=ctime()))
threads=[]
t1=threading.Thread(target=Music,args=("FILL ME",))
t2=threading.Thread(target=Blog,args=("python",))

threads.append(t1)
threads.append(t2)
if __name__ == '__main__':
    for t in threads:
        t.start()
        # t.join() # 最后出现主程序 等t1  t2执行完之后
    # t1.join()  #t1线程不结束 其他线程不能执行 先执行t1,t2 然后在执行t1结束之后再执行主线程
    t2.join() #t1 t2执行完之后再打印主程序

    print("all over %s" %ctime())

 

setDeamon(True)  

       将线程声明为守护线程,必须在start()方法调用之前设置,如果不设置为守护线程程序会被无限挂起。

       当我们在程序运行中,执行一个主线程,如果主线程有创建一个子线程 就兵分两路,分别运行,那么当主线程完成

       想退出时,会检验子线程是否完成,如果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是只要主线程

       完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以用setDeamon方法啦

import threading
import time
from time import ctime,sleep

def Music(name):
    print("Begin listening to {name}".format(name=name,time=ctime()))
    sleep(3)
    print("end listenting{time}".format(time=ctime()))
def Blog(title):
    print("Begin recording the {title}".format(title=title,time=ctime ()))
    sleep(5)
    print("end recording the {time}".format(time=ctime()))
threads=[]
t1=threading.Thread(target=Music,args=("FILL ME",))
t2=threading.Thread(target=Blog,args=("python",))

threads.append(t1)
threads.append(t2)
if __name__ == '__main__':
    # 守护线程跟着主线程走,t1 t2两个都设置为守护线程,主线程执行完 其他就都不执行
    # t1.setDaemon(True)  #把t1设置为守护线程,等待t2执行结束,但是t1也需要执行,正常执行
    t2.setDaemon(True) #把t2设置为守护线程,主线程结束,t2也就跟着结束,不执行
    for t in threads: #for遍历
        t.start()
  
    print("all over %s" %ctime())

其他方法:

 Thread实例对象的方法

 isAlive():返回线程是否活动的

 getName():返回线程名

 setName():设置线程名

 

threading模块提供的一些方法:

 threading.currentThread(): 返回当前的线程变量。

 threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

 threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

 

8 GIL(全局解释锁)

Python中的线程是操作系统的原生线程,python虚拟机使用一个全局解释器锁(Global Interpreter Lock)来互斥线程对python虚拟机的使用。为了支持多线程机制,一个基本的要求就是需要实现不同线程对共享资源访问的互斥,所有引入了GIL。

加在C python解释其上,为了支持多线程机制,一个基本的要求就是需要实现不同线程对共享资源访问的互斥,所以引入了GIL。

GIL:在一个线程拥有了解释器的访问权之后,其他的所有线程都必须等他它释放解释器的访问权,即使这些线程的下一条指令并不会互相影响。

在调用任何Python  C  API之前,要先获得GIL

GIL缺点:多处理器退化为单处理器;优先:避免大量的加解锁操作

GIL的影响

无论你启多个线程,你有多少个cpu,Python在执行一个进程的时候会谈定的在同一时刻只允许一个线程运行。

所有,python是无法利用多核CPU实现多线程的

这样,python对于计算机密型的任务开多线程的效率甚至不如串行(没有大量切换),但是,对于IO密集型的任务效率还是有显著提升的。

 

import time

def cal(n):
    sum=0
    for i in range(n):
        sum+=i

s=time.time()

# import threading
# t1=threading.Thread(target=cal,args=(10000000,))
# t2=threading.Thread(target=cal,args=(10000000,))
#
# t1.start()
# t2.start()
# t1.join()
# t2.join()
# # time 10.940000057220459
# # time 1.1090002059936523

cal(10000000)
cal(10000000)

print("time",time.time()-s)
# time 10.986999750137329
# time 1.128000020980835

计算密集型:一直在使用CPU

IO:存在大量IO操作

总结:对于计算密集型任务:Python的多线程并没有用

        对于IO密集型任务:Python的多线程是有意义的

Python使用多核:开进程,弊端:开销大而且切换复杂

 

posted @ 2017-05-08 20:15  karina梅梅  阅读(289)  评论(0编辑  收藏  举报