进程与线程

什么是进程和线程?

进程是加载到内存,正在被执行的程序。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单位。线程是比进程还小的运行基本单元,一个进程至少有一个线程。线程是一种轻量级的进程,多线程处理就是允许一个进程中在同一时刻执行多个任务。

进程和线程的区别?

  • 进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位(进程——资源分配的最小单位,线程——程序执行的最小单位)
  • 在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
  • 进程由CPU轮询调度,线程由所处进程进行调度。
  • 内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
  • 包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

并行与并发

并行是指同一时刻同时做多件事情,而并发是指同一时间间隔内做多件事情。并行的必要条件就是CPU核心数 >= 总进程数 ,并发是多个进程在一个CPU上交替进行,但看上去好像是一起执行。

在python中多进程实现并行

python模块——multiprocessing

大致流程:

  1. 实例化一个进程,参数分别是函数名、可选参数*args、可选参数**kwargs。
  2. 开启进程

下面是一个小例子

import multiprocessing
import time

print("start--{}".format(time.asctime(time.localtime(time.time()))))
def run():
    print("start1--{}".format(time.asctime(time.localtime(time.time()))))
    time.sleep(5)#模拟阻塞任务
    print("end1--{}".format(time.asctime(time.localtime(time.time()))))
pro = multiprocessing.Process(target=run)
pro.start()
time.sleep(5)#模拟阻塞任务
print("end--{}".format(time.asctime(time.localtime(time.time()))))
start--Sat Oct 20 23:49:04 2018
start1--Sat Oct 20 23:49:04 2018
end--Sat Oct 20 23:49:09 2018
end1--Sat Oct 20 23:49:09 2018

上述运行结果表明运行时间为5秒,上述代码有两个阻塞任务,每个阻塞任务都会耗时5秒,正常情况下,运行时间应该为10秒,但这里为两个阻塞多开了一个进程,即在同一时间同时处理这两个阻塞,所以耗时为5秒。下面是未开进程的代码及运行结果。

import time

print("start--{}".format(time.asctime(time.localtime(time.time()))))
def run():
    print("start1--{}".format(time.asctime(time.localtime(time.time()))))
    time.sleep(5)#模拟阻塞任务
    print("end1--{}".format(time.asctime(time.localtime(time.time()))))
run()
time.sleep(5)#模拟阻塞任务
print("end--{}".format(time.asctime(time.localtime(time.time()))))
start--Sat Oct 20 23:53:44 2018
start1--Sat Oct 20 23:53:44 2018
end1--Sat Oct 20 23:53:49 2018
end--Sat Oct 20 23:53:54 2018

上述运行时间为10秒

什么是GIL锁?

python在设计的时候还没有多核处理器的概念,因此为了设计方便与线程安全,直接设计了一个锁,这个锁要求在任何进程中,一次只能有一个线程运行,因此python并不能为多个线程分配多个CPU,所以python中的线程只能实现并发,不能实现真正的并行。但在python3中的GIL锁有一个很棒的的设计,那就是在遇到阻塞时会自动切换线程。

利用线程避开阻塞任务

python模块——threading

大致流程:

  1. 实例化一个线程,参数分别是函数名、可选参数*args、可选参数**kwargs。
  2. 开启线程
import threading
import time

print("start--{}".format(time.asctime(time.localtime(time.time()))))
def run():
    print("start1--{}".format(time.asctime(time.localtime(time.time()))))
    time.sleep(5)#模拟阻塞任务
    print("end1--{}".format(time.asctime(time.localtime(time.time()))))
pro = threading.Thread(target=run)
pro.start()
time.sleep(5)#模拟阻塞任务
print("end--{}".format(time.asctime(time.localtime(time.time()))))
start--Sun Oct 21 00:08:22 2018
start1--Sun Oct 21 00:08:22 2018
end--Sun Oct 21 00:08:27 2018
end1--Sun Oct 21 00:08:27 2018

运行时间为5秒,说明开辟的线程避开了阻塞任务。

多线程实现并发服务器

由于线程能有效的避开阻塞任务,故可以利用这一点实现服务端的多线程并发。

import socket
import threading

server = socket.socket()
server.bind(('127.0.0.5',8520))
server.listen(50)
def func(a):
    date = a.recv(1024)
    if date:
        print("已收到信息-->{}".format(date.decode()))
        a.send(date)
    else:
        a.close()

while True:
    a, b = server.accept()
    pro = threading.Thread(target=func,args = (a,))
    pro.start()

多进程实现并发服务器

import socket
import multiprocessing

server = socket.socket()
server.bind(('127.0.0.5',8520))
server.listen(50)
def func(a):
    date = a.recv(1024)
    if date:
        print("已收到信息-->{}".format(date.decode()))
        a.send(date)
    else:
        a.close()

while True:
    a, b = server.accept()
    pro = multiprocessing.Process(target=func,args = (a,))
    pro.start()

 

posted @ 2018-10-21 00:41  龙~白  阅读(184)  评论(0编辑  收藏  举报