0
0
DbmsConceptBeginner · 4 min read

Strict Two Phase Locking: Definition, Example, and Use Cases

Strict Two Phase Locking (Strict 2PL) is a concurrency control method in databases where all locks held by a transaction are released only after the transaction commits or aborts. This ensures serializability and prevents other transactions from seeing intermediate changes, maintaining data consistency.
⚙️

How It Works

Strict Two Phase Locking works by dividing a transaction's life into two phases: a growing phase where it acquires locks but does not release any, and a shrinking phase where it releases all locks only after the transaction finishes (commits or aborts). This means no other transaction can access the locked data until the current transaction is fully done.

Imagine you are writing a letter and locking the drawer where you keep your drafts. You keep the drawer locked while writing and only unlock it after finishing the letter. This way, no one else can peek or change your draft midway, ensuring your work stays consistent.

By holding all locks until the end, strict 2PL prevents problems like dirty reads, where one transaction sees uncommitted changes from another, making the database safe and reliable.

💻

Example

This example simulates two transactions accessing a shared data item using strict two phase locking to avoid conflicts.

java
import java.util.HashMap;
import java.util.Map;

class LockManager {
    private final Map<String, String> locks = new HashMap<>();

    public synchronized boolean acquireLock(String transaction, String dataItem) {
        if (!locks.containsKey(dataItem)) {
            locks.put(dataItem, transaction);
            System.out.println(transaction + " acquired lock on " + dataItem);
            return true;
        } else if (locks.get(dataItem).equals(transaction)) {
            return true; // already locked by this transaction
        } else {
            System.out.println(transaction + " waiting for lock on " + dataItem);
            return false;
        }
    }

    public synchronized void releaseLocks(String transaction) {
        locks.entrySet().removeIf(entry -> entry.getValue().equals(transaction));
        System.out.println(transaction + " released all locks");
    }
}

class Transaction implements Runnable {
    private final String name;
    private final LockManager lockManager;

    public Transaction(String name, LockManager lockManager) {
        this.name = name;
        this.lockManager = lockManager;
    }

    @Override
    public void run() {
        // Growing phase: acquire locks
        while (!lockManager.acquireLock(name, "DataItem1")) {
            try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
        }
        // Simulate work
        System.out.println(name + " is processing DataItem1");
        try { Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }

        // Commit phase: release locks
        lockManager.releaseLocks(name);
        System.out.println(name + " committed transaction");
    }
}

public class Strict2PLExample {
    public static void main(String[] args) throws InterruptedException {
        LockManager lockManager = new LockManager();
        Thread t1 = new Thread(new Transaction("T1", lockManager));
        Thread t2 = new Thread(new Transaction("T2", lockManager));

        t1.start();
        Thread.sleep(50); // Start T2 shortly after T1
        t2.start();

        t1.join();
        t2.join();
    }
}
Output
T1 acquired lock on DataItem1 T1 is processing DataItem1 T2 waiting for lock on DataItem1 T1 released all locks T1 committed transaction T2 acquired lock on DataItem1 T2 is processing DataItem1 T2 released all locks T2 committed transaction
🎯

When to Use

Strict Two Phase Locking is best used in database systems where data consistency and correctness are critical, such as banking, booking systems, and inventory management. It prevents problems like dirty reads and ensures that transactions appear to run one after another, even if they run at the same time.

Use strict 2PL when you want to avoid complex errors caused by concurrent data access and when the cost of waiting for locks is acceptable compared to the risk of inconsistent data.

Key Points

  • Strict 2PL holds all locks until transaction commit or abort.
  • Prevents dirty reads and ensures serializability.
  • Divides transaction into growing and shrinking phases.
  • Commonly used in systems requiring strong data consistency.
  • May cause waiting or blocking but improves correctness.

Key Takeaways

Strict Two Phase Locking ensures data consistency by holding locks until transaction completion.
It prevents other transactions from seeing uncommitted changes, avoiding dirty reads.
Use strict 2PL in critical systems where correctness is more important than speed.
It divides transaction locking into a growing phase (acquire locks) and shrinking phase (release locks).
Strict 2PL may cause waiting but guarantees serializable transaction execution.