
- Python - Home
- Python - Overview
- Python - History
- Python - Features
- Python vs C++
- Python - Hello World Program
- Python - Application Areas
- Python - Interpreter
- Python - Environment Setup
- Python - Virtual Environment
- Python - Basic Syntax
- Python - Variables
- Python - Data Types
- Python - Type Casting
- Python - Unicode System
- Python - Literals
- Python - Operators
- Python - Arithmetic Operators
- Python - Comparison Operators
- Python - Assignment Operators
- Python - Logical Operators
- Python - Bitwise Operators
- Python - Membership Operators
- Python - Identity Operators
- Python - Operator Precedence
- Python - Comments
- Python - User Input
- Python - Numbers
- Python - Booleans
- Python - Control Flow
- Python - Decision Making
- Python - If Statement
- Python - If else
- Python - Nested If
- Python - Match-Case Statement
- Python - Loops
- Python - for Loops
- Python - for-else Loops
- Python - While Loops
- Python - break Statement
- Python - continue Statement
- Python - pass Statement
- Python - Nested Loops
- Python Functions & Modules
- Python - Functions
- Python - Default Arguments
- Python - Keyword Arguments
- Python - Keyword-Only Arguments
- Python - Positional Arguments
- Python - Positional-Only Arguments
- Python - Arbitrary Arguments
- Python - Variables Scope
- Python - Function Annotations
- Python - Modules
- Python - Built in Functions
- Python Strings
- Python - Strings
- Python - Slicing Strings
- Python - Modify Strings
- Python - String Concatenation
- Python - String Formatting
- Python - Escape Characters
- Python - String Methods
- Python - String Exercises
- Python Lists
- Python - Lists
- Python - Access List Items
- Python - Change List Items
- Python - Add List Items
- Python - Remove List Items
- Python - Loop Lists
- Python - List Comprehension
- Python - Sort Lists
- Python - Copy Lists
- Python - Join Lists
- Python - List Methods
- Python - List Exercises
- Python Tuples
- Python - Tuples
- Python - Access Tuple Items
- Python - Update Tuples
- Python - Unpack Tuples
- Python - Loop Tuples
- Python - Join Tuples
- Python - Tuple Methods
- Python - Tuple Exercises
- Python Sets
- Python - Sets
- Python - Access Set Items
- Python - Add Set Items
- Python - Remove Set Items
- Python - Loop Sets
- Python - Join Sets
- Python - Copy Sets
- Python - Set Operators
- Python - Set Methods
- Python - Set Exercises
- Python Dictionaries
- Python - Dictionaries
- Python - Access Dictionary Items
- Python - Change Dictionary Items
- Python - Add Dictionary Items
- Python - Remove Dictionary Items
- Python - Dictionary View Objects
- Python - Loop Dictionaries
- Python - Copy Dictionaries
- Python - Nested Dictionaries
- Python - Dictionary Methods
- Python - Dictionary Exercises
- Python Arrays
- Python - Arrays
- Python - Access Array Items
- Python - Add Array Items
- Python - Remove Array Items
- Python - Loop Arrays
- Python - Copy Arrays
- Python - Reverse Arrays
- Python - Sort Arrays
- Python - Join Arrays
- Python - Array Methods
- Python - Array Exercises
- Python File Handling
- Python - File Handling
- Python - Write to File
- Python - Read Files
- Python - Renaming and Deleting Files
- Python - Directories
- Python - File Methods
- Python - OS File/Directory Methods
- Python - OS Path Methods
- Object Oriented Programming
- Python - OOPs Concepts
- Python - Classes & Objects
- Python - Class Attributes
- Python - Class Methods
- Python - Static Methods
- Python - Constructors
- Python - Access Modifiers
- Python - Inheritance
- Python - Polymorphism
- Python - Method Overriding
- Python - Method Overloading
- Python - Dynamic Binding
- Python - Dynamic Typing
- Python - Abstraction
- Python - Encapsulation
- Python - Interfaces
- Python - Packages
- Python - Inner Classes
- Python - Anonymous Class and Objects
- Python - Singleton Class
- Python - Wrapper Classes
- Python - Enums
- Python - Reflection
- Python Errors & Exceptions
- Python - Syntax Errors
- Python - Exceptions
- Python - try-except Block
- Python - try-finally Block
- Python - Raising Exceptions
- Python - Exception Chaining
- Python - Nested try Block
- Python - User-defined Exception
- Python - Logging
- Python - Assertions
- Python - Built-in Exceptions
- Python Multithreading
- Python - Multithreading
- Python - Thread Life Cycle
- Python - Creating a Thread
- Python - Starting a Thread
- Python - Joining Threads
- Python - Naming Thread
- Python - Thread Scheduling
- Python - Thread Pools
- Python - Main Thread
- Python - Thread Priority
- Python - Daemon Threads
- Python - Synchronizing Threads
- Python Synchronization
- Python - Inter-thread Communication
- Python - Thread Deadlock
- Python - Interrupting a Thread
- Python Networking
- Python - Networking
- Python - Socket Programming
- Python - URL Processing
- Python - Generics
- Python Libraries
- NumPy Tutorial
- Pandas Tutorial
- SciPy Tutorial
- Matplotlib Tutorial
- Django Tutorial
- OpenCV Tutorial
- Python Miscellenous
- Python - Date & Time
- Python - Maths
- Python - Iterators
- Python - Generators
- Python - Closures
- Python - Decorators
- Python - Recursion
- Python - Reg Expressions
- Python - PIP
- Python - Database Access
- Python - Weak References
- Python - Serialization
- Python - Templating
- Python - Output Formatting
- Python - Performance Measurement
- Python - Data Compression
- Python - CGI Programming
- Python - XML Processing
- Python - GUI Programming
- Python - Command-Line Arguments
- Python - Docstrings
- Python - JSON
- Python - Sending Email
- Python - Further Extensions
- Python - Tools/Utilities
- Python - GUIs
- Python Advanced Concepts
- Python - Abstract Base Classes
- Python - Custom Exceptions
- Python - Higher Order Functions
- Python - Object Internals
- Python - Memory Management
- Python - Metaclasses
- Python - Metaprogramming with Metaclasses
- Python - Mocking and Stubbing
- Python - Monkey Patching
- Python - Signal Handling
- Python - Type Hints
- Python - Automation Tutorial
- Python - Humanize Package
- Python - Context Managers
- Python - Coroutines
- Python - Descriptors
- Python - Diagnosing and Fixing Memory Leaks
- Python - Immutable Data Structures
- Python Useful Resources
- Python - Questions & Answers
- Python - Interview Questions & Answers
- Python - Online Quiz
- Python - Quick Guide
- Python - Reference
- Python - Cheatsheet
- Python - Projects
- Python - Useful Resources
- Python - Discussion
- Python Compiler
- NumPy Compiler
- Matplotlib Compiler
- SciPy Compiler
Python - Synchronizing Threads
In Python, when multiple threads are working concurrently with shared resources, it's important to synchronize their access to maintain data integrity and program correctness. Synchronizing threads in python can be achieved using various synchronization primitives provided by thethreading module, such as locks, conditions, semaphores, and barriers to control access to shared resources and coordinate the execution of multiple threads.
In this tutorial, we'll learn about various synchronization primitives provided by Python'sthreading module.
Thread Synchronization using Locks
The lock object in the Python's threading module provide the simplest synchronization primitive. They allow threads to acquire and release locks around critical sections of code, ensuring that only one thread can execute the protected code at a time.
A new lock is created by calling theLock() method, which returns a lock object. The lock can be acquired using theacquire(blocking) method, which force the threads to run synchronously. The optional blocking parameter enables you to control whether the thread waits to acquire the lock and released using therelease() method.
Example
The following example demonstrates how to use locks (the threading.Lock() method) to synchronize threads in Python, ensuring that multiple threads access shared resources safely and correctly.
import threadingcounter = 10def increment(theLock, N): global counter for i in range(N): theLock.acquire() counter += 1 theLock.release()lock = threading.Lock()t1 = threading.Thread(target=increment, args=[lock, 2])t2 = threading.Thread(target=increment, args=[lock, 10])t3 = threading.Thread(target=increment, args=[lock, 4])t1.start()t2.start()t3.start()# Wait for all threads to completefor thread in (t1, t2, t3): thread.join()print("All threads have completed")print("The Final Counter Value:", counter)
Output
When the above code is executed, it produces the following output −
All threads have completedThe Final Counter Value: 26
Condition Objects for Synchronizing Python Threads
Condition variables enable threads to wait until notified by another thread. They are useful for providingcommunication between the threads. Thewait() method is used to block a thread until it is notified by another thread throughnotify() ornotify_all().
Example
This example demonstrates how Condition objects can synchronize threads using thenotify() andwait() methods.
import threadingcounter = 0 # Consumer functiondef consumer(cv): global counter with cv: print("Consumer is waiting") cv.wait() # Wait until notified by increment print("Consumer has been notified. Current Counter value:", counter)# increment functiondef increment(cv, N): global counter with cv: print("increment is producing items") for i in range(1, N + 1): counter += i # Increment counter by i # Notify the consumer cv.notify() print("Increment has finished")# Create a Condition objectcv = threading.Condition()# Create and start threadsconsumer_thread = threading.Thread(target=consumer, args=[cv])increment_thread = threading.Thread(target=increment, args=[cv, 5])consumer_thread.start()increment_thread.start()consumer_thread.join()increment_thread.join()print("The Final Counter Value:", counter)
Output
On executing the above program, it will produce the following output −
Consumer is waitingincrement is producing itemsIncrement has finishedConsumer has been notified. Current Counter value: 15The Final Counter Value: 15
Synchronizing threads using the join() Method
Thejoin() method in Python's threading module is used to wait until all threads have completed their execution. This is a straightforward way to synchronize the main thread with the completion of other threads.
Example
This demonstrates synchronization of threads using thejoin() method to ensure that the main thread waits for all started threads to complete their work before proceeding.
import threadingimport timeclass 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) print_time(self.name, self.counter, 3) def print_time(threadName, delay, counter): while counter: time.sleep(delay) print("%s: %s" % (threadName, time.ctime(time.time()))) counter -= 1 threads = []# Create new threadsthread1 = MyThread(1, "Thread-1", 1)thread2 = MyThread(2, "Thread-2", 2)# Start the new Threadsthread1.start()thread2.start()# Join the threadsthread1.join()thread2.join()print("Exiting Main Thread")
Output
On executing the above program, it will produce the following output −
Starting Thread-1Starting Thread-2Thread-1: Mon Jul 1 16:05:14 2024Thread-2: Mon Jul 1 16:05:15 2024Thread-1: Mon Jul 1 16:05:15 2024Thread-1: Mon Jul 1 16:05:16 2024Thread-2: Mon Jul 1 16:05:17 2024Thread-2: Mon Jul 1 16:05:19 2024Exiting Main Thread
Additional Synchronization Primitives
In addition to the above synchronization primitives, Python's threading module offers: −
- RLocks (Reentrant Locks): A variant of locks that allow a thread to acquire the same lock multiple times before releasing it, useful in recursive functions or nested function calls.
- Semaphores:Similar to locks but with a counter. Threads can acquire the semaphore up to a certain limit defined during initialization. Semaphores are useful for limiting access to resources with a fixed capacity.
- Barriers: Allows a fixed number of threads to synchronize at a barrier point and continue executing only when all threads have reached that point. Barriers are useful for coordinating a group of threads that must all complete a certain phase of execution before any of them can proceed further.