进程和线程概览

一、进程和线程概论

1.什么是进程?

程序是存储在磁盘中的可执行的数据。
进程可以看作是程序的一次执行,每个进程都有自己的内存空间和数据栈。
进程间只能通讯,而不能直接共享信息。

2.什么是线程?

一个进程中可以有多个线程,一个进程中线程共享运行环境,也就是有相同的内存空间、数据栈等。
比如你启动了一个python项目,允许同时100人访问,你就可以人为在python进程中,同时开了100个线程。
虽然一个进程中的线程共享数据,但是每个线程都拥有自己的栈空间和执行队列。

3.进程和线程的关系?

进程和线程的最大区别在于操作系统对其不同的资源管理方式。

一个程序至少有一个进程,一个进程至少有一个线程。
一个进程的崩溃并不会影响其它进程的运行,但是如果一个线程崩溃掉了,当前进程中的线程都会崩掉,因为共享数据。

从逻辑的角度来讲,多线程的意义在于,在一个应用程序中,有多个执行部分可以同时执行。
但是操作系统并不会把多个线程当作单独的应用来对其调度、管理和资源控制。

多线程共享数据,自然可以极大的提高程序的运行效率。
多线程虽然开销小,但是不利于管理,线程则于其刚好相反,同时健壮性更强。

4.并发与并行

并行:物理上具备同一时刻处理多个任务的能力。
并发:逻辑上具备同一时刻处理多个任务的能力。
虽然说并发可以同时里处理多个任务,但是并不是一定要同时执行。

并行一定发生在多核CPU上,并行是并发设计的理想模式。
单核机器上的并发是通过间隔方式切换执行。
单线程通过协程的方式实现并发,协程是主动切换任务来实现的。

python由于GIL锁的缘故,只能实现并发而不能并行。

 

二、进程和线程的开启方式

1、进程

方式1:

from multiprocessing import Process
import time

def task1(num):
    print("开始执行任务task1")
    time.sleep(num)
    print("任务task1执行结束")

def task2(num):
    print("开始执行任务task2")
    time.sleep(num)
    print("任务task2执行结束")

if __name__ == "__main__":
    p1 = Process(target=task1,args=(5,))
    p2 = Process(target=task2,args=(3,))
    p1.start()
    p2.start()
    
# 执行结果:
# 开始执行任务task1
# 开始执行任务task2
# 任务task2执行结束
# 任务task1执行结束

  方式2:

from multiprocessing import Process
import time

class TestProcess(Process):
    def __init__(self,num):
        super().__init__()
        self.num = num

    def run(self):
        print("任务task开始执行")
        time.sleep(self.num)
        print("任务task执行结束")
    

if __name__ == "__main__":
    my_process = TestProcess(5)
    my_process.start()

2.线程

方式1:

from threading import Thread
import time

def task1(num):
    print("开始执行任务task1")
    time.sleep(num)
    print("任务task1执行结束")

def task2(num):
    print("开始执行任务task2")
    time.sleep(num)
    print("任务task2执行结束")

if __name__ == "__main__":
    p1 = Thread(target=task1,args=(5,))
    p2 = Thread(target=task2,args=(3,))
    p1.start()
    p2.start()

方式2:

from threading import Thread
import time

class TestThread(Thread):
    def __init__(self,num):
        super().__init__()
        self.num = num

    def run(self):
        print("任务task开始执行")
        time.sleep(self.num)
        print("任务task执行结束")


if __name__ == "__main__":
    my_process = TestThread(5)
    my_process.start()

 

三、锁

1.进程同步锁

上锁之后,将会串行,不会并发执行。

from multiprocessing import Process,Lock
import time

def task1(num,lock):
    lock.acquire()
    print("开始执行任务task1")
    time.sleep(num)
    print("任务task1执行结束")
    lock.release()

def task2(num,lock):
    lock.acquire()
    print("开始执行任务task2")
    time.sleep(num)
    print("任务task2执行结束")
    lock.release()

if __name__ == "__main__":
    lock = Lock()
    p1 = Process(target=task1,args=(5,lock))
    p2 = Process(target=task2,args=(3,lock))
    p1.start()
    p2.start()

 

四、进程池和线程池

1.进程池

from concurrent.futures import ProcessPoolExecutor
import os,random,time
def func(name):
    print("%s吃了又一碗饭:%s" %(name,os.getpid()))
    time.sleep(random.randint(1, 3))

if __name__ == "__main__":
    p = ProcessPoolExecutor(3)  #创建一个进程池,里面容纳3个进程
    for i in range(7):
        obj = p.submit(func,'科比%i'%i)
    p.shutdown(wait=True)  #类似与join,并且可以关门,以防在等的过程中又提交新的任务
    print("主进程")
    
#执行结果:
科比0吃了又一碗饭:13980
科比1吃了又一碗饭:9636
科比2吃了又一碗饭:12660
科比3吃了又一碗饭:13980
科比4吃了又一碗饭:12660
科比5吃了又一碗饭:9636
科比6吃了又一碗饭:13980
主进程

 

2.线程池

from threading import Thread,current_thread
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time,os
def task(n):
    print('%s is running'% current_thread().getName())
    time.sleep(3)
    return  n**2

if __name__ =="__main__":
    t = ThreadPoolExecutor(3)   #默认是CPU的核数*5
    objs = []
    for i in range(7):
        obj = t.submit(task,i)
        objs.append(obj)
    t.shutdown(wait=True)  #异步,最终打印结果
    for obj in objs:
        print(obj.result())
    print("",current_thread().getName())


执行结果:
ThreadPoolExecutor-0_0 is running
ThreadPoolExecutor-0_1 is running
ThreadPoolExecutor-0_2 is running
ThreadPoolExecutor-0_2 is running
ThreadPoolExecutor-0_1 is running
ThreadPoolExecutor-0_0 is running
0
1
4
ThreadPoolExecutor-0_1 is running
9
16
25
36
主 MainThread

 

五 、守护进程和守护线程

无论是进程还是线程,当主进程结束的时候,守护进程也会随之结束。

from multiprocessing import Process
import os,time,random

def task():
    print('%s is running '%os.getpid())
    time.sleep(2)

    print('%s is done' % os.getppid())

if __name__ == "__main__":
    p = Process(target=task)
    p.daemon = True   #1.必须在进程开启之前  2.不能再开启子进程
    p.start()
    print("")

 

posted @ 2019-08-02 16:16  明王不动心  阅读(166)  评论(0编辑  收藏  举报