python线程执行代码封装和执行顺序

本文详细介绍了Python中使用threading模块进行多线程编程的方法,包括如何定义线程类、重写run方法以及理解线程执行的不确定性。通过具体示例,展示了线程的封装性和执行顺序的特点。

线程-注意点

1. 线程执行代码的封装

通过上一小节,能够看出,通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法

示例如下:

#coding=utf-8
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I'm "+self.name+' @ '+str(i) #name属性中保存的是当前线程的名字
            print(msg)


if __name__ == '__main__':
    t = MyThread()
    t.start()

说明
python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。

2. 线程的执行顺序

#coding=utf-8
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I'm "+self.name+' @ '+str(i)
            print(msg)
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()
执行结果:(运行的结果可能不一样,但是大体是一致的)

    I'm Thread-1 @ 0
    I'm Thread-2 @ 0
    I'm Thread-5 @ 0
    I'm Thread-3 @ 0
    I'm Thread-4 @ 0
    I'm Thread-3 @ 1
    I'm Thread-4 @ 1
    I'm Thread-5 @ 1
    I'm Thread-1 @ 1
    I'm Thread-2 @ 1
    I'm Thread-4 @ 2
    I'm Thread-5 @ 2
    I'm Thread-2 @ 2
    I'm Thread-1 @ 2
    I'm Thread-3 @ 2

说明
从代码和执行结果我们可以看出,多线程程序的执行顺序是不确定的。当执行到sleep语句时,线程将被阻塞(Blocked),到sleep结束后,线程进入就绪(Runnable)状态,等待调度。而线程调度将自行选择一个线程执行。上面的代码中只能保证每个线程都运行完整个run函数,但是线程的启动顺序、run函数中每次循环的执行顺序都不能确定。

3. 总结

每个线程默认有一个名字,尽管上面的例子中没有指定线程对象的name,但是python会自动为线程指定一个名字。
当线程的run()方法结束时该线程完成。
无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。

<think>嗯,用户问的是Python中的线程同步,特别是如何让线程顺序执行S1、S2、S3。首先,我需要确定用户的需求是什么。可能他们正在处理多线程程序,需要确保某些任务按特定顺序执行,避免竞态条件或者数据一致的问题。 首先,我应该回忆一下Python线程同步的基本机制。常用的有锁(Lock)、事件(Event)、条件变量(Condition)、信号量(Semaphore)屏障(Barrier)等。用户提到的顺序执行,可能需要用到锁或者条件变量来控制线程执行顺序。 用户提到先执行S1,然后是S2S3。可能的场景是S1必须在S2S3之前成,而S2S3可以并行执行,或者需要按顺序执行。需要确认用户的具体情况,但根据问题描述,可能S1先执行,然后S2S3接着执行,可能两者可以并行,也可能需要依次执行过原问题中的“先S1在执行S2 S3”可能意味着S1之后依次执行S2S3,或者S2S3在S1之后并行。需要进一步分析。 假设用户希望S1执行后,再依次执行S2S3,或者S2S3在S1之后可以同时运行。同的情况需要同的同步方法。比如,如果S2S3需要在S1之后并行执行,可以用事件或者信号量;如果S2S3需要依次执行,可能需要更多的锁或条件。 可能需要举几个例子来说明同的同步方法。例如,使用Lock来确保S1先执行,然后释放锁让S2S3执行过Lock通常用于互斥访问资源,可能太适合顺序控制。而Condition变量更适合这种情况,因为它可以等待某个条件满足后再继续执行。 另一个可能性是使用Event对象。S1线程设置一个事件,S2S3线程等待该事件被设置后再执行。这样可以确保S1成后,S2S3才开始。 或者使用Barrier,过Barrier通常用于多个线程到达某个点后再一起继续,可能太适合这里的顺序执行。 接下来需要思考如何编写示例代码。比如,使用threading.Event:S1执行后设置事件,S2S3在启动前等待事件被触发。这样S2S3会等待S1成后再执行,但它们之间可能会并行执行,取决于如何启动线程。 如果用户希望S1成后,按顺序执行S2,然后S3,那么可能需要更严格的同步,比如每个线程等待前一个线程成。这时候可以用多个锁或者条件变量,或者按顺序启动线程,但这样可能无法充分利用多线程的优势,因为变成了顺序执行过,可能用户的问题中的S2S3是可以并行执行的,只要在S1之后。所以正确的同步方式是确保S1先成,然后S2S3同时执行。这种情况下,Event或Condition是合适的。 现在,我需要整理这些思路,给出结构清晰的回答。首先介绍线程同步的必要性,然后详细说明几种方法,如Event、Condition,可能还有Lock的结合使用,并提供代码示例。同时要注意线程启动的顺序,可能需要让S2S3先等待,然后启动S1,再启动S2S3,或者调整线程的启动顺序。 另外,要确保示例代码的正确性。比如,在使用Event时,S2S3的线程会在event.wait()处阻塞,直到S1调用event.set()。这样就能保证S1先执行毕,然后S2S3开始执行。但S2S3的执行顺序是否确定呢?可能它们的执行顺序由操作系统调度决定,如果用户需要S2在S3之前,可能需要额外的同步。 如果用户希望S1->S2->S3的顺序,每个步骤都严格按顺序执行,那么可能需要每个线程触发下一个线程执行,这可能更复杂,比如使用多个事件或条件。或者,如果用户只是需要S1先执行,然后S2S3可以同时执行,那么Event就足够。 可能需要分情况讨论:一种是S1之后S2S3并行,另一种是S1之后依次执行S2S3。在回答中应涵盖这两种情况,或者根据用户的问题判断。原问题中的“先S1在执行S2 S3”可能更倾向于S1之后按顺序执行S2S3,但用户可能只是想让S1先于S2S3执行,而S2S3之间没有顺序要求。 因此,在回答中应该明确说明同的情况,并提供相应的解决方案。例如,使用Event或Condition让S1先执行,然后S2S3可以同时执行,或者使用多个锁确保S1->S2->S3的顺序。 最后,代码示例需要正确使用同步原语,并展示如何启动线程。同时提醒用户注意线程启动的顺序,比如先启动S2S3的线程,但它们会等待事件,然后启动S1的线程,这样S1执行后,S2S3才能继续。 总结:回答需要分步骤说明线程同步的必要性,介绍同的同步机制,给出示例代码,并解释其工作原理,同时指出同方法的适用场景。确保用户能够根据需求选择合适的同步方式。</think>在Python中,线程同步可通过多种机制实现顺序控制。以下是逐步说明如何实现“先执行`S1`,再执行`S2``S3`”: --- ### 1. **线程同步的必要性** 多线程并发执行时,若未同步可能导致: - 竞态条件(Race Condition) - 执行顺序可预测 - 资源访问冲突 --- ### 2. **实现方法** #### 方法1:使用`threading.Event` ```python import threading # 定义事件 event = threading.Event() def task_S1(): print("S1 执行成") event.set() # 通知其他线程 def task_S2(): event.wait() # 等待S1成 print("S2 执行成") def task_S3(): event.wait() # 等待S1成 print("S3 执行成") # 创建线程 t1 = threading.Thread(target=task_S1) t2 = threading.Thread(target=task_S2) t3 = threading.Thread(target=task_S3) # 启动线程(注意顺序:先启动S2/S3,再启动S1) t2.start() t3.start() t1.start() ``` #### 方法2:使用`threading.Condition` ```python import threading condition = threading.Condition() s1_done = False def task_S1(): global s1_done with condition: print("S1 执行成") s1_done = True condition.notify_all() # 唤醒所有等待线程 def task_S2(): with condition: while not s1_done: condition.wait() # 等待S1成 print("S2 执行成") def task_S3(): with condition: while not s1_done: condition.wait() # 等待S1成 print("S3 执行成") # 启动线程(同上) t1 = threading.Thread(target=task_S1) t2 = threading.Thread(target=task_S2) t3 = threading.Thread(target=task_S3) t2.start() t3.start() t1.start() ``` #### 方法3:使用`threading.Lock`(适用于严格串行) ```python import threading lock = threading.Lock() def task_S1(): with lock: print("S1 执行成") def task_S2(): with lock: print("S2 执行成") def task_S3(): with lock: print("S3 执行成") # 按顺序启动线程 t1 = threading.Thread(target=task_S1) t2 = threading.Thread(target=task_S2) t3 = threading.Thread(target=task_S3) t1.start() t1.join() # 等待S1成 t2.start() t2.join() # 等待S2成 t3.start() ``` --- ### 3. **关键点总结** - **`Event``Condition`的区别**: - `Event`适合一对多通知(如S1成后触发多个线程)。 - `Condition`适合复杂条件判断(如依赖多个状态)。 - **线程启动顺序**: - 若使用`Event`或`Condition`,需先启动等待线程(S2/S3),再启动触发线程(S1)。 - **锁的粒度**: - `Lock`适合强制串行化,但会降低并发性能。 --- ### 4. **扩展场景** - **若需S1→S2→S3严格顺序**:使用`join()`或链式同步。 - **若S2/S3可并行**:使用`Event`或`Condition`通知多个线程。 - **若需复用同步逻辑**:封装为类或上下文管理器。 通过合理选择同步机制,可确保线程执行顺序符合预期。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值