Python系统编程-进程、进程池,线程,线程同步一文全解

本文深入探讨Python的进程和线程概念,包括进程与线程的区别,使用thread和threading模块创建线程,通过Queue模块实现线程同步,以及如何运用进程池管理大量进程。示例代码详细解释了每个概念的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文章参考自书籍Python程序员面试宝典

1、 任务?进程?线程?

1、首先我们理解一下什么是进程?什么是线程?
操作系统同时运行多个任务。一个任务就是一个进程。
进程就是我们运行的程序。这是我们的电脑运行的任务管理器。
在这里插入图片描述
对于线程而言,线程是进程的基本单位,一个进程至少有一个线程,但是如果一个进程只有一个线程的哈,那么这个线程一般被叫做主线程。
在这里插入图片描述

2、 thread创建新线程

Python提供多线程模块thread和threading,以及队列Queue,其中thread是比较基础的,不容易控制,而且thread参看底层堆栈内存,所以一般我们都是用threading。
下面就是用thread模块中的start_new_thread函数来产生新线程。

# 使用thread的start_new_thread创建新线程
import _thread
import time

def print_time(threadName,delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print("%s : %s"%(threadName,time.ctime(time.time())))

# 创建两个线程
try:
    _thread.start_new_thread(print_time,("Thread-1",2,))
    _thread.start_new_thread(print_time,("Thread-2",4,))
except:
    print("Error:unable to start thread ")

while 1:
    pass

运行结果:
在这里插入图片描述
线程一般都是依靠线程函数的自然结束,也可以在线程函数中调用thread.exit()函数来抛出系统异常(SystemExitexception),然后就可以退出线程。

3、threading 创建线程

Python的标准库中thread提供的是比较低级,原始的线程以及一个简单的锁。
threading模块提供的方法包括:

threading.currentThread():返回当前线程变量
threading.enumerate():返回一个正在运行的线程list
threading.activeCount():返回正在运行的线程数量

如何用threading创建新线程?
自定义一个threading.Thread的类,然后重写__init__ 方法和run方法。

# thread提供一些比较低级别的,原始线程以及一个简单的锁
import threading
import time
exitFlag = 0


# 集成父类 threading.Thread
# noinspection PyStatementEffect
class myThread(threading.Thread):
    def __init__(self,threadID,name,counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
# 把要执行的代码写到run函数里面,线程在创建之后直接运行run函数
    def run(self):
        print("starting"+self.name)
        print_time(self.name,self.counter,5)
        #print_time(self.name,self.counter,5)
        print("Exiting"+self.name)

def print_time(threadName,delay,counter):
    while counter:
        if exitFlag:
            (threading.Thread).exit()
        time.sleep(delay)
        print("%s:%s"%(threadName,time.ctime(time.time())))
        counter -= 1

# 创建新线程
thread1 = myThread(1,"Thread-1",1)
thread2 = myThread(2,"Thread-2",2)

# 开启线程
thread1.start()
thread2.start()
print("Exiting Main Thread")

运行结果:
在这里插入图片描述

4、如何保持线程同步?

如果多个线程对某个数据修改,则可以出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
使用thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需求每次只允许一个线程操作的数据,可以将其操作放在acquire和release之间。
多线程的优势在于可以同时完成多个任务,但是当线程需要数据共享的时候,可能存在数据不同步的问题。

"""
多个线程如果对于某个数据修改,则可以产生不可预料的结果为了保证某个数据的正确性,就需要对某个线程进行同步
"""
import threading
import time

class myThread(threading.Thread):
    def __init__(self,threadID,name,counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter

    def run(self):
        print("Starting"+self.name)
        # 获得锁,成功获得锁定后返回True
        # 可选的timeout 参数不填时候将一直阻塞,直到锁定
        # 否则超时后将返回false
        threadLock.acquire()
        print_time(self.name,self.counter,3)
        threadLock.release()

def print_time(threadName,delay,counter):
    while counter:
        time.sleep(delay)
        print("%s:%s"%(threadName,time.ctime(time.time())))
        counter -= 1
threadLock = threading.Lock()
threads = []

# 创建新线程
thread1 = myThread(1,"Thread-1",1)
thread2 = myThread(2,"Thread-2",2)

# 开启新线程
thread1.start()
thread2.start()

# 添加新线程到线程列表
threads.append(thread1)
threads.append(thread2)

# 等待所有的线程完成
for t in threads:
    t.join()
print("Exiting Main Thread")

运行结果:
在这里插入图片描述

5、Queue模块

Python的Queue模块主要提供同步的,线程安全的队列类,包括FIFO(先进先出)队列Queue、LIFO(后进先出)队列LifoQueue和优先级队列,这些队列实现锁原语,能够在多线程中直接使用,可以使用队列来实现线程之间同步。
下面一个示例来实现一个先进先出的示例:

import queue
import threading
import time

exitFlag = 0

class myThread(threading.Thread):
    def __init__(self, threadID, name, q):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q

    # 把要执行的代码写到run函数里面,线程在创建之后直接运行run函数
    def run(self):
        print("starting" + self.name)
        process_data(self.name, self.q)
        print("Exiting"+self.name)
def process_data(threadName,q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            queueLock.release()
            print("%s processing %s"%(threadName,data))
        else:
            queueLock.release()
        time.sleep(1)
threadList = ["Thread-1","Thread-2","Thread-3"]
nameList = ["one two","three","four","five",]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1

# 创建新线程
for tName in threadList:
    thread = myThread(threadID,tName,workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

# 填充队列
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# 等待队列清空
while not workQueue.empty():
    pass

# 通知线程时候退出
exitFlag = 1

# 等待所有的线程完成
for t in threads:
    t.join()
print("Exiting Main Thread")

运行结果:
在这里插入图片描述

6、进程池

进程池毫无疑问就是去创建和销毁大量的进程的,手动创建并管理大量的进程是特别复杂和繁琐的,如果创建的进程不是很多,那么Process就可以用.

Pool类可以提供指定数量的进程供用户调用,当有新的请求提交到# 当需要的子进程特别多的时候,就需要进程池了,Pool类可以提供指定数量的进程供用户调用如果有新的请求提交到Pool中时,如果进程池还没有满,那么就会创建一个新的进程来执行请求。

from multiprocessing import Pool
import os
import random
import time
def task(name):
    print("Run task %s(%s)..."%(name,os.getpid()))
    time.sleep(random()*3)

if __name__ == '__main__':
    print("parent process %s"%os.getpid())
    p = Pool(5) # 最大进程为5
    for i in range(8):
        p.apply_async(task,args=(i,)) # 进程池中添加子进程"
    print("waiting for all subprocesses done...")
    p.close() #关闭Pool,不在接收其他新的任务
    p.join()
    print('All subprocesses done...')
"""
对于Pool对象调用join()方法等待所有的子进程执行完毕
调用join()之前必须提前调用close()
调用close()之后就不能继续添加新的process了
"""

运行结果:
在这里插入图片描述
好久没学习啦,水平有限,大家多多纠正指导!
如果大家觉得敲代码这些比较麻烦,可以直接在我的主页资源里面下载哦!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鹏鹏写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值