Skip to content

Latest commit

 

History

History
71 lines (45 loc) · 2.72 KB

File metadata and controls

71 lines (45 loc) · 2.72 KB

Concurrency, Parallelism and Asynchronous Programming: Threading

Overview of Threading in Python

Threading is a technique for achieving concurrency where multiple threads are spawned by a process to execute tasks concurrently. It's particularly useful for I/O-bound tasks where the program has to wait for external resources.

Python's Threading Module

Python provides the threading module, which is a high-level interface for working with threads.

Basic Usage
  1. Creating Threads: Use the Thread class from the threading module. Pass the target function and its arguments to the constructor.

    import threading
    
    def print_numbers():
        for i in range(1, 6):
            print(i)
    
    # Creating a thread
    thread = threading.Thread(target=print_numbers)
    thread.start()
  2. Joining Threads: The join method waits for threads to complete their execution.

    thread.join()
  3. Daemon Threads: These are background threads that are killed when all non-daemon threads have completed.

    thread = threading.Thread(target=print_numbers, daemon=True)

Thread Synchronization

To avoid the issues arising from multiple threads accessing the same data, synchronization mechanisms like locks can be used.

Using Locks
  1. Lock: A Lock can be used to ensure that only one thread can access a particular section of the code at a time.

    lock = threading.Lock()
    
    def safe_print(item):
        with lock:
            print(item)
    
    # Lock will be acquired before printing and released after printing

Challenges with Threading

  • Global Interpreter Lock (GIL): In CPython, the GIL is a mutex that allows only one thread to execute in the interpreter at once. This means that threads are not as efficient for CPU-bound tasks.
  • Concurrency Issues: Issues like race conditions, deadlocks, and data corruption can occur if not handled properly.

Best Practices

  • Use for I/O-bound Tasks: Threading in Python is best used for I/O-bound tasks.
  • Avoid for CPU-bound Tasks: For CPU-bound operations, consider using multiprocessing.
  • Proper Synchronization: Use synchronization primitives to avoid concurrent access to shared resources.
  • Thread-safe Libraries: Ensure that the libraries and functions used are thread-safe.

Conclusion

Threading in Python can be a powerful tool for achieving concurrency, especially for I/O-bound tasks. However, it's important to understand its limitations, particularly the impact of the GIL on CPU-bound tasks. Proper management of threads, along with careful handling of shared resources and synchronization, is crucial for writing efficient and safe threaded applications.