Nearby lessons

141 of 159

Python - Synchronization

📌 What You Will Learn
  • Explain why synchronization is required in multi threading
  • Identify the data inconsistency problem without synchronization
  • Understand the critical section concept
  • Recognize application areas of synchronization
  • Describe how synchronization solves the shared-resource problem

Synchronization

If multiple Threads are executing simultaneously, then there may be a chance of data inconsistency problems.

This problem can occur when multiple Threads access the same shared resource at the same time.

To overcome this problem, we should use Synchronization.

Simple Definition:

Synchronization means allowing Threads to execute one by one so that data inconsistency problems can be avoided.

The document defines it simply as:

Synchronization means
at a time only one Thread.

Why Do We Need Synchronization?

In Multi Threading, multiple Threads can execute simultaneously.

This is useful for improving concurrency, but it can create problems when multiple Threads work with the same shared resource.

For example:

Thread-1
    │
    ▼
Shared Resource
    ▲
    │
Thread-2

If both Threads access the shared resource at the same time, their executions may overlap.

This overlapping execution can create:

  • Data inconsistency problems
  • Irregular output

Problem Without Synchronization

Consider two Threads executing the same function simultaneously.

Thread-1 ───────┐
                │
                ▼
            wish()
                ▲
                │
Thread-2 ───────┘

Both Threads enter the same function at approximately the same time.

The execution of one Thread may overlap with the execution of another Thread.

As a result, we may get mixed or irregular output.

Example Program - Without Synchronization

🐍Code Cell
1from threading import *
2import time
3 
4def wish(name):
5 for i in range(10):
6 print("Good Evening:", end='')
7 time.sleep(2)
8 print(name)
9 
10t1 = Thread(target=wish, args=("Dhoni",))
11t2 = Thread(target=wish, args=("Yuvraj",))
12 
13t1.start()
14t2.start()
Output
No output captured.

Output

Important Note About the Output

The exact order of the output can vary from one execution to another because Thread scheduling is not fixed.

The important observation from the example is that the output becomes mixed.

Instead of getting:

Good Evening:Dhoni
Good Evening:Dhoni

or

Good Evening:Yuvraj
Good Evening:Yuvraj

we may get output such as:

Good Evening:Good Evening:Yuvraj
Dhoni

This happens because both Threads are executing the same function simultaneously.

Program Explanation

Step 1: Import Required Modules

from threading import *
import time

The threading module is used for creating Threads.

The time module is used for delaying execution by using:

time.sleep()

Step 2: Create the Shared Function

def wish(name):

The wish() function is the shared function.

The same function will be executed by multiple Threads.


Step 3: Repeat Ten Times

for i in range(10):

Each Thread executes the loop ten times.

Therefore:

Thread t1
   │
   ▼
10 Iterations

Thread t2
   │
   ▼
10 Iterations

Step 4: Print the Greeting

print("Good Evening:", end='')

This statement prints:

Good Evening:

The end='' argument prevents print() from moving to the next line.

Therefore, Python waits for the next output to continue on the same line.


Step 5: Pause the Thread

time.sleep(2)

After printing Good Evening:, the currently executing Thread sleeps for two seconds.

This delay gives another Thread an opportunity to execute.


Step 6: Print the Name

print(name)

After the sleep period, the Thread prints the name passed to the function.

For example:

Dhoni

or

Yuvraj

Step 7: Create Two Threads

t1 = Thread(target=wish, args=("Dhoni",))
t2 = Thread(target=wish, args=("Yuvraj",))

Two Child Threads are created.

Both Threads execute the same wish() function.

Thread Function Argument
t1 wish() "Dhoni"
t2 wish() "Yuvraj"

Step 8: Start Both Threads

t1.start()
t2.start()

After starting both Threads, they execute concurrently.

There is no synchronization mechanism in this program.

Therefore, both Threads can enter wish() and their executions can overlap.

How the Irregular Output is Produced

Consider one possible execution.

Step 1

Thread t1 executes:

print("Good Evening:", end='')

Output:

Good Evening:

Step 2

Thread t1 executes:

time.sleep(2)

Now t1 sleeps.


Step 3

During this period, Thread t2 gets a chance to execute:

print("Good Evening:", end='')

The output can now become:

Good Evening:Good Evening:

Step 4

After the sleeping Threads resume, the names may be printed:

Yuvraj
Dhoni

Therefore, we can get:

Good Evening:Good Evening:Yuvraj
Dhoni

This is an example of irregular output caused by overlapping Thread execution.

Execution Flow Without Synchronization

Program Starts
      │
      ▼
Create Thread t1
      │
      ▼
Create Thread t2
      │
      ▼
Start t1
      │
      ▼
t1 Enters wish()
      │
      ▼
Print "Good Evening:"
      │
      ▼
t1 Sleeps
      │
      ├────────────────────┐
      │                    │
      │                    ▼
      │                t2 Executes
      │                    │
      │                    ▼
      │             Enters wish()
      │                    │
      │                    ▼
      │           Print "Good Evening:"
      │                    │
      └────────────┬───────┘
                   │
                   ▼
            Threads Resume
                   │
                   ▼
             Names Printed
                   │
                   ▼
              Mixed Output

Why Are We Getting This Output?

We are getting irregular output because both Threads are executing the wish() function simultaneously.

The execution of one Thread overlaps with the execution of another Thread.

As a result:

  • Both Threads can print Good Evening: almost at the same time.
  • The names can be printed in an irregular order.
  • The output becomes mixed.
t1 ─────► Good Evening:
              │
              ▼
            sleep()

t2 ─────► Good Evening:
              │
              ▼
            sleep()

Both Resume
     │
     ▼
Names Printed
in Scheduler-Dependent Order

What Is the Problem?

Simultaneous execution can cause:

  • Irregular output
  • Data inconsistency problems

This happens because multiple Threads are accessing the same function or shared resource at the same time.

Multiple Threads
       │
       ▼
Same Shared Resource
       │
       ▼
Simultaneous Access
       │
       ▼
Overlapping Execution
       │
       ▼
Irregular Output /
Data Inconsistency

Data Inconsistency

Data inconsistency means the shared data may not remain in the expected or correct state when multiple Threads modify or access it simultaneously without proper coordination.

Conceptually:

Shared Data
    │
    ├────────► Thread-1
    │
    └────────► Thread-2
         │
         ▼
Both Access
Simultaneously
         │
         ▼
Unexpected Result

The example in this section demonstrates the problem using irregular output.

How Can We Solve This Problem?

To overcome this problem, we should use:

Synchronization

Synchronization controls access to the shared resource.

Instead of allowing multiple Threads to execute the critical work simultaneously, the Threads are coordinated so that only the permitted Thread accesses it at that time.

Without Synchronization

Thread-1 ───┐
            ├──► Shared Resource
Thread-2 ───┘


With Synchronization

Thread-1 ─────► Shared Resource
                    │
                    ▼
                Complete
                    │
                    ▼
Thread-2 ─────► Shared Resource

What Is Synchronization?

In synchronization, Threads are executed one by one for the protected work so that we can overcome data inconsistency problems.

Definition:

Synchronization means at a time only one Thread.

In simple words:

Thread-1
   │
   ▼
Execute Protected Work
   │
   ▼
Complete / Release
   │
   ▼
Thread-2
   │
   ▼
Execute Protected Work

This prevents overlapping access to the synchronized shared resource.

Execution Without Synchronization

Start
  │
  ▼
Thread-1 Starts
  │
  ├────────────────┐
  │                │
  ▼                ▼
Thread-1       Thread-2 Starts
Executing      Simultaneously
  │                │
  └────────┬───────┘
           │
           ▼
    Overlapping Work
           │
           ▼
       Mixed Output
           │
           ▼
    Data Inconsistency

Without synchronization, multiple Threads can access the same shared resource concurrently.

Execution With Synchronization

Start
  │
  ▼
Thread-1 Executes
Protected Work
  │
  ▼
Thread-1 Finishes /
Releases Resource
  │
  ▼
Thread-2 Executes
Protected Work
  │
  ▼
Thread-2 Finishes
  │
  ▼
Correct / Regular
Result

Synchronization prevents the protected operations of the Threads from interfering with one another.

Without Synchronization vs With Synchronization

Without Synchronization With Synchronization
Multiple Threads may access the shared resource simultaneously. Shared access is controlled.
Thread executions may overlap. Protected execution occurs one Thread at a time.
Output may become mixed. Output becomes regular for the protected operation.
Data inconsistency may occur. Data inconsistency can be avoided.
Shared resource can be accessed together. Shared resource is accessed according to synchronization control.

Main Application Areas of Synchronization

The document gives the following common application areas of Synchronization:

  1. Online Reservation System
  2. Funds Transfer from Joint Accounts
  3. etc.

Example - Online Reservation System

Consider an Online Reservation System.

Multiple users may try to reserve the same seat at approximately the same time.

Available Seat
      │
      ├────────► User / Thread-1
      │
      └────────► User / Thread-2

If access to the reservation operation is not controlled properly, conflicting updates can occur.

Synchronization can protect the critical reservation operation so that shared booking data is updated safely.

Example - Funds Transfer from Joint Accounts

Another application mentioned in the document is:

Funds Transfer
from Joint Accounts

If multiple Threads perform operations on the same shared account data simultaneously, incorrect updates may occur.

Synchronization can ensure that the critical balance-update operation is properly coordinated.

Shared Account
     │
     ▼
Thread-1 Requests Access
     │
     ▼
Protected Operation
     │
     ▼
Thread-1 Completes
     │
     ▼
Thread-2 Gets Access

Important Concept - Critical Section

The part of a program that accesses shared data and therefore requires controlled access is commonly called a critical section.

def wish(name):

    # Critical / Protected Work
    print("Good Evening:", end='')
    time.sleep(2)
    print(name)

Synchronization mechanisms are used to control access to such protected code.

In the upcoming section, the document uses:

Lock

to implement synchronization.

Conceptual Execution Flow

Multiple Threads
       │
       ▼
Need Shared Resource
       │
       ▼
Is Synchronization
Used?
       │
   ┌───┴────┐
   │        │
   ▼        ▼
  No       Yes
   │        │
   ▼        ▼
Threads    Controlled
Overlap    Access
   │        │
   ▼        ▼
Mixed      One Thread
Output     at a Time
   │        │
   ▼        ▼
Possible   Regular /
Data       Consistent
Problem    Result

Synchronization Does Not Mean Only One Thread Exists

Synchronization does not mean that the entire Python program can contain only one Thread.

Multiple Threads can still exist.

The important point is that access to the synchronized shared resource is controlled.

Python Program
     │
     ├────► Thread-1
     ├────► Thread-2
     └────► Thread-3

All Threads Exist

But

Critical Shared Resource
        │
        ▼
Controlled Access

This distinction is important when understanding Lock, RLock, and Semaphore.

What Comes After Synchronization?

Synchronization is the general concept.

Python's threading module provides synchronization mechanisms to implement it.

The document continues with:

Synchronization
      │
      ▼
Lock
      │
      ▼
RLock
      │
      ▼
Semaphore

The next topic starts with Synchronization Using Lock.

Summary

Topic Description
Simultaneous Execution Multiple Threads execute concurrently.
Problem Execution may overlap when shared resources are accessed.
Irregular Output Output from multiple Threads can become mixed.
Data Inconsistency Shared data may produce unexpected results.
Solution Synchronization
Synchronization Controls Thread access to shared resources.
Document Definition At a time only one Thread.
Application 1 Online Reservation System
Application 2 Funds Transfer from Joint Accounts

Important Notes

  1. Simultaneous execution of multiple Threads may create data inconsistency problems.
  2. The wish() function demonstrates this problem using irregular output.
  3. Both t1 and t2 execute the same wish() function.
  4. Thread t1 receives "Dhoni" as its argument.
  5. Thread t2 receives "Yuvraj" as its argument.
  6. The irregular output occurs because both Threads execute the same function concurrently and their operations overlap.
  7. time.sleep(2) pauses the currently executing Thread for two seconds.
  8. During the sleep period, another Thread can execute.
  9. Because end='' is used, Good Evening: is printed without immediately moving to the next line.
  10. Without synchronization, the output can therefore become mixed.
  11. Synchronization is used to overcome data inconsistency problems.
  12. The document defines synchronization as: at a time only one Thread.
  13. Synchronization coordinates access to shared resources.
  14. Online Reservation Systems are an application area of synchronization.
  15. Funds Transfer from Joint Accounts is another application area mentioned in the document.
  16. The next section implements synchronization using a Lock.
📝 Key Takeaways
  • Simultaneous access to a shared resource causes data inconsistency
  • Synchronization serializes access to the critical section
  • Synchronization does not mean only one thread exists
  • Online reservation and joint account transfer are real examples

🧠 Test Your Knowledge

15 Questions
Progress: 0 / 15