一、程序

  1)程序:是指令和数据的集合,其本身没有任何运行的含义,是一个静态的概念。进程中的文本区域就是代码区,也就是程序。

  2)Python标准库中提供两个模块,_thread和threading,_thread是低级模块,threading是高级模块,是对_thread进行了封装,绝大多数情况下,我们只需要使用threading这个高级模块。启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行。

import threading

def run():
    print("任务开始!")

# 创建进程,程序本身就是一个线程,叫做主线程

t1 = threading.Thread(target=run)   # 创建子线程

# 启动线程
run()            # 启动主线程
t1.start()      # 启动子线程


>>任务开始!
>>任务开始!

二、进程

  1)进程:就是一段程序的执行过程,是一个动态的概念。它是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

  2)进程的概念主要有两点:第一,进程是一个实体,每一个进程都有它自己的地址空间,一般包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域储存处理器执行的代码;数据区域储存变量和进程执行期间使用的动态分布的内存;堆栈区域储存活动过程调用的指令和本地变量。第二,进程是一个执行中的程序,程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称之为进程。

  3)进程有三个状态(就绪、运行和阻塞):就绪态,其实就是获取cpu外的所有资源,只要处理器分配资源就可以马上执行;运行态,获得了处理器分配的资源,程序开始执行;阻塞态,当程序条件不够时,需要等待条件满足时才能执行,如等待I/O操作时候,此刻的状态就叫阻塞态。

Python基础知识(程序、进程与线程)_创建进程

 

   4)单进程/多进程执行案例

# 运用多进程操作模式,可以实现多个任务同时并行操作。
# 创建多进程
from multiprocessing import Process
import time

def run(name):
    print(name,"进程执行了!")
    time.sleep(2)

if __name__ == "__main__":
    # 创建进程
    p1 = Process(target=run,args=("p1",))
    p2 = Process(target=run, args=("p2",))
    p3 = Process(target=run, args=("p3",))

    # 启动进程
    p1.start()
    p2.start()
    p3.start()


>>p1 进程执行了!   # 多个任务同时运行
>>p2 进程执行了!
>>p3 进程执行了!

三、线程

  1)线程:通常一个进程中可以包含多个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源,我们把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。(若把进程比作一列火车,线程类似于火车车厢,单线程就像一个车厢)。

  2)多线程:多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提供资源使用效率来提高系统的效率。(多线程就像火车的多个车厢)

  3)单线程与多线程区别:刚开始直板洛基亚手机是单线程操作的,想听音乐和发短信两件事,只能按照先后顺序一种一种的来操作;现在的智能手机是多线程操作模式的,我们可以同时听音乐、发短信及同时做其他的事情。

  4)单线程/多线程执行案例

# 单线程
import threading
import time

def run(n):
    print("任务开始!", n)
    time.sleep(5)

# 创建进程
t1 = threading.Thread(target=run, args=("t1",))

t1.start()


>>任务开始! t1
>>[finished in 5s]    # 单线程走完使用了5s
# 多进程
import threading
import time

def run(n):
    print("任务开始!", n)
    time.sleep(5)

# 创建进程
# 程序本身就是一个线程,叫做主线程,手动创建的线程叫子线程。
t1 = threading.Thread(target=run, args=("t1",))
t2 = threading.Thread(target=run, args=("t2",))

# 启动进程
t1.start()   # 通常主线程的执行中不会等待子线程执行完毕,就会直接执行后面的代码
t2.start()

t1.join()   # 等待子线程执行完毕之后再执行主线程内容。
t2.join()

print("执行完毕!")


>>任务开始! t1
>>任务开始! t2
>>执行完毕!
>>[finished in 5.1s]    # 多线程走完只用了5.1s,若分别使用单线程的话需要10s。

  5)线程锁(互斥锁)

# 线程锁(全局解释器锁GIL):不管电脑系统cpu核心数量是多少,保证Python程序中,同一时间只能执行一个线程。

import threading

lock = threading.Lock()   # 创建一个线程锁(互斥锁)

num = 5
def run(name):
    lock.acquire()       # 设置线程锁
    global num           # 设置num为全局变量
    num = num - 1
    print(f"线程{num}执行了!")
    lock.release()       # 释放线程锁

# 创建进程,设置5个子线程
for i in range(5):
    t = threading.Thread(target=run,args=(i+1,))   # 创建子线程

    # 启动线程
    t.start()      # 启动子线程


>>线程4执行了!
>>线程3执行了!
>>线程2执行了!
>>线程1执行了!
>>线程0执行了!

四、进程和线程的区别

  1)进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响。线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但是线程之间没有单独的地址空间,一个线程死掉就等于整个进程也同时死掉。所以多进程的程序要比多线程的程序健壮,但是进程切换时,耗费资源较大,效率要差一些。对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程。

  2)简而言之,一个程序运行至少有一个进程,一个进程至少有一个线程;线程的尺度小于进程,使得多线程的程序并发性高;进程在执行过程中拥有独立的内存单元,而多线程共享内存,电脑中的RAM(简称运存),从而极大的提高了程序的运行效率。

  3)一台单核电脑同一时间只能处理一个进程中的一个线程,但可实现多线程不停切换。一台8核电脑同一时间可同时处理8个线程。