杰瑞科技汇

Python thread start如何正确使用?

Of course! Let's break down how to start a thread in Python, from the basic concept to practical examples and best practices.

Python thread start如何正确使用?-图1
(图片来源网络,侵删)

The Core Concept: threading.Thread

In Python, the threading module is the primary way to work with threads. The key object is the Thread class.

To start a thread, you follow these two simple steps:

  1. Create a Thread object: You tell it which function (or method) it should run.
  2. Call the .start() method: This is the crucial step. It tells the Python interpreter to actually begin executing the function in a new, separate thread of control.

Basic Example: A Simple Function

Let's start with the most straightforward case: running a simple function in a new thread.

import threading
import time
def my_function(seconds):
    """A simple function that waits for a given number of seconds."""
    thread_id = threading.get_ident()
    print(f"Thread {thread_id}: Started. Will sleep for {seconds} seconds.")
    time.sleep(seconds)
    print(f"Thread {thread_id}: Finished sleeping.")
# --- Main part of the script ---
if __name__ == "__main__":
    print("Main script: Starting a new thread.")
    # 1. Create a Thread object.
    #    - `target`: The function the thread will execute.
    #    - `args`: A tuple of arguments to pass to the target function.
    my_thread = threading.Thread(target=my_function, args=(5,))
    # 2. Start the thread.
    #    This tells the OS to create a new thread and begin running my_function in it.
    my_thread.start()
    print("Main script: The new thread has been started.")
    print("Main script: I can do other work here while the other thread is running.")
    # 3. Wait for the thread to complete (optional but highly recommended).
    #    The main script will pause at this line until my_thread has finished.
    my_thread.join()
    print("Main script: The new thread has finished. Exiting.")

Output (will be slightly different each time due to timing):

Python thread start如何正确使用?-图2
(图片来源网络,侵删)
Main script: Starting a new thread.
Main script: The new thread has been started.
Thread 140123456789120: Started. Will sleep for 5 seconds.
Main script: I can do other work here while the other thread is running.
Thread 140123456789120: Finished sleeping.
Main script: The new thread has finished. Exiting.

Key Points:

  • target=my_function: This specifies the "worker" function.
  • args=(5,): We pass arguments to the target function as a tuple. Notice the comma: (5,) is a tuple with one element, while (5) is just the number 5.
  • .start(): This is the magic method. It doesn't run the function immediately; it schedules it to run in a new thread.
  • .join(): This is essential for synchronization. It makes the main thread wait until the thread you join() has completed. Without it, the main script might exit before your new thread has a chance to finish.

Example: Using a Class Method as the Target

It's very common to encapsulate thread logic in a class.

import threading
import time
class TaskRunner:
    def __init__(self, duration):
        self.duration = duration
    def run_task(self):
        """This method will be executed by the thread."""
        thread_id = threading.get_ident()
        print(f"Class Thread {thread_id}: Running task for {self.duration} seconds.")
        time.sleep(self.duration)
        print(f"Class Thread {thread_id}: Task complete.")
if __name__ == "__main__":
    runner = TaskRunner(3)
    # Create the thread, targeting the instance method
    class_thread = threading.Thread(target=runner.run_task)
    print("Main script: Starting the class-based thread.")
    class_thread.start()
    print("Main script: Doing other things...")
    class_thread.join()
    print("Main script: Class-based thread finished.")

Sharing Data Between Threads (The Challenge)

Threads share the same memory space. This is powerful but dangerous. If multiple threads try to read and write the same variable at the same time, you can get race conditions, leading to corrupted or unpredictable data.

Example of a Race Condition:

Python thread start如何正确使用?-图3
(图片来源网络,侵删)
import threading
# A shared variable
shared_counter = 0
def increment_counter():
    global shared_counter
    for _ in range(1_000_000):
        shared_counter += 1 # This is NOT an atomic operation
if __name__ == "__main__":
    threads = []
    for _ in range(5):
        thread = threading.Thread(target=increment_counter)
        threads.append(thread)
        thread.start()
    for thread in threads:
        thread.join()
    print(f"Final counter value: {shared_counter}")
    # Expected: 5,000,000
    # Actual: Almost always a number much lower than that!

Why does this happen? The line shared_counter += 1 involves three steps:

  1. Read shared_counter from memory.
  2. Add 1 to it.
  3. Write the new value back to memory.

If two threads interleave these steps, they can read the same old value, both add 1, and both write back the same new value, effectively losing one increment.

The Solution: Locks

To fix this, we use a Lock (also called a mutex). A lock ensures that only one thread can execute a specific piece of code at a time.

import threading
shared_counter = 0
# Create a lock object
lock = threading.Lock()
def increment_counter_safe():
    global shared_counter
    for _ in range(1_000_000):
        with lock: # Acquire the lock, execute block, then release it automatically
            shared_counter += 1
if __name__ == "__main__":
    threads = []
    for _ in range(5):
        thread = threading.Thread(target=increment_counter_safe)
        threads.append(thread)
        thread.start()
    for thread in threads:
        thread.join()
    print(f"Final counter value: {shared_counter}")
    # Output: Final counter value: 5000000 (Correct!)

The with lock: statement:

  • When a thread enters the with block, it tries to acquire the lock.
  • If the lock is available, it gets it and executes the code inside the block.
  • If another thread already holds the lock, the first thread will wait (block) until the lock is released.
  • When the with block is exited (even if an error occurs), the lock is automatically released. This prevents deadlocks from forgetting to release a lock.

Summary: Key Steps to Start a Thread

  1. Import the module: import threading
  2. Define a target function: This is the code your thread will execute.
  3. Create the Thread object:
    • my_thread = threading.Thread(target=your_function, args=(arg1, arg2))
  4. Start the thread: my_thread.start()
  5. (Recommended) Wait for completion: my_thread.join()
  6. (If sharing data) Use a Lock: lock = threading.Lock() and wrap critical code in with lock:.
分享:
扫描分享到社交APP
上一篇
下一篇