进程和线程

进程

广义定义:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。

狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。

在操作系统中引入进程的概念,是为了实现多个程序的并发执行。

进程的状态

进程的创建

Linux操作系统:

import os
print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork() #创建一个子进程
if pid == 0:
    print('I am child process (%s) and my parent is %s.' % (os.getpid(), 
os.getppid()))
else:
    print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
import os
import time

cnt = 100

print('Process (%s) (%s) start...' % (os.getpid(), os.getppid()))
# Only works on Unix/Linux/Mac:
pid = os.fork() #创建一个子进程
if pid == 0:
    time.sleep(3)
    print(cnt, 'I am child process (%s) and my parent is %s.' % (os.getpid(),os.getppid()))
else:
    cnt = 1000
    print(cnt, 'I (%s) just created a child process (%s).' % (os.getpid(), pid))

    #os.wait()
    while True:
        pass

fork() 调用一次返回两次

在父进程中返回大于0的值pid,pid:子进程的pid(进程id)

在子进程中返回0

os.getpid(): 获取当前进程的pid

os.getppid(): 获取父进程的pid

windows操作系统:

from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
    print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('Child process will start.')
p.start()
p.join()
print('Child process end.')

进程函数传参

import os
import time

# 子进程要执行的代码
def run_proc(*args):
    print(args[0], args[1])

if __name__=='__main__':
    p = Process(target=run_proc, args=('test1',"test2"))
    p.start()
    p.join() #阻塞等待子进程退出,并且回收子进程的资源
    print('Child process end.')

进程池

from multiprocessing import Pool
import os, time, random

def worker(msg):
    t_start = time.time()
    print("%s开始执行,进程号为%d" % (msg,os.getpid()))
    # random.random()随机生成0~1之间的浮点数
    time.sleep(random.random()*2)
    t_stop = time.time()
    print(msg,"执行完毕,耗时%0.2f" % (t_stop-t_start))

if __name__ == "__main__":
    po = Pool(5)  # 定义一个进程池,最大进程数5
    for i in range(0,10):
        po.apply_async(worker,(i,))  # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))

    for i in range(100,110):
        po.apply_async(worker,(i,))  # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))

    print("----start----")
    po.close()  # 关闭进程池,关闭后po不再接收新的请求
    po.join()  # 等待po中所有子进程执行完成,再执行下面的代码,可以设置超时时间join(timeout=)
    print("-----end-----")

孤儿进程和僵尸进程

子进程是父进程的拷贝。

父子进程拥有自己独立的地址空间。

孤儿进程:如果一个进程的父进程先于他自己退出,那么这个进程就叫做孤儿进程。

僵尸进程:Linux中一个进程'退出'以后其实并没有真正退出,而是系统将其状态标记为“zombie”状态,如果该进程的父进程没有回收子进程的系统资源,则该进程就叫僵尸进程。危害:浪费系统资源。

如何防止僵尸进程?

一般,为了防止产生僵尸进程,在fork子进程之后我们都要wait它们;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。

线程

线程:进程内部的执行分支, 是系统进行任务调度的最小单元。

线程的查看:

ps -eLf

  PID        PPID     LWP C NLWP CMD

    进程ID   父进程ID

    LWP:light weight process 轻量级进程 => 线程

线程的创建

import time, threading

#线程函数
def loop():
    print('thread %s is running...' % threading.current_thread().name)

#打印当前运行的线程的名称
print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start() #启动线程
t.join() #阻塞等待子线程退出
print('thread %s ended.' % threading.current_thread().name)

线程数据的同步

互斥锁/互斥量 mutex

A、创建锁 mutex = threading.Lock()

B、加锁 mutex.acquire()

C、解锁 mutex.release()

import time, threading

cnt = 0

#构造一个互斥锁
mutex = threading.Lock()

#子线程 线程函数
def loop():
    global cnt
    #mutex.acquire()
    for i in range(1000000):
        #加锁
        mutex.acquire()
        cnt += 1
        #解锁
        mutex.release()
    #mutex.release()
    print(threading.current_thread().name, ": ", cnt)
    print('thread %s is running...' % threading.current_thread().name)

#主线程
#打印当前运行的线程的名称
print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start() #启动线程

t1 = threading.Thread(target=loop, name='LoopThread1')
t1.start() #启动线程

t2 = threading.Thread(target=loop, name='LoopThread2')
t2.start() #启动线程

t.join() #阻塞等待子线程退出
t1.join() #阻塞等待子线程退出
t2.join()
print("MainThread: ", cnt)

print('thread %s ended.' % threading.current_thread().name)

线程数据的访问

import time, threading

cnt = 100

#子线程 线程函数
def loop():
    global cnt
    cnt = 1000
    print(threading.current_thread().name, ": ", cnt)
    print('thread %s is running...' % threading.current_thread().name)

def loop1():
    global cnt
    print(threading.current_thread().name, ": ", cnt)
    cnt = 2000
    print(threading.current_thread().name, ": ", cnt)
    print('thread %s is running...' % threading.current_thread().name)

#主线程
#打印当前运行的线程的名称
print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start() #启动线程

t1 = threading.Thread(target=loop1, name='LoopThread1')
t1.start() #启动线程

t.join() #阻塞等待子线程退出
t1.join() #阻塞等待子线程退出
print("MainThread: ", cnt)

 

posted @ 2020-05-24 14:05  独剑飞行天下  阅读(256)  评论(0)    收藏  举报