Java.Multithreading.When to use what ?

🔎 Key Criteria to Decide:

  1. Do you need mutual exclusion?
  2. Do you need only visibility or atomicity?
  3. Do you need fine-grained locking or advanced features like try-lock, fairness, etc.?
  4. Are threads coordinating around a condition (like a signal or phase)?

Let’s look at each scenario 👇

🧵 1. Use synchronized when:

✅ You need:

  • Basic mutual exclusion
  • Simplicity and safety
  • Minimal code (Java handles lock acquire/release automatically)

❌ Avoid if:

  • You need interruption, timeout, or non-blocking attempts
  • You need complex coordination

🔧 Example:

public synchronized void increment() {
    count++;
}

📌 Use it for most simple locking needs, especially when guarding an entire method or small critical section.

🔒 2. Use ReentrantLock when:

✅ You need:

  • Advanced control over locking, like:
    • tryLock()
    • lockInterruptibly()
    • Fairness policy
    • Manual unlocking
  • Condition variables (newCondition()), which are more powerful than wait()/notify()

❌ Avoid if:

  • You don’t need that control — synchronized is cleaner and safer

🔧 Example:

lock.lock();
try {
    // critical section
} finally {
    lock.unlock(); // always required manually
}

📌 Use for low-level, performance-critical, or condition-driven logic.

⚡ 3. Use Atomic Variables (AtomicInteger, etc.) when:

✅ You need:

  • Lock-free atomic operations
  • Simple counters, flags, or compare-and-set logic
  • High performance

❌ Not suitable for:

  • Complex logic involving multiple shared variables
  • Coordinating across threads with blocking

🔧 Example:

AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();

📌 Great for lightweight concurrent counters or flags.

👁️ 4. Use volatile when:

✅ You need:

  • Visibility guarantee only
  • One thread writes, others read
  • You want to avoid locking

❌ Don’t use for compound actions (e.g. ++, check-then-act)

🔧 Example:

volatile boolean running = true;

📌 Use it for simple flags or safe publication (e.g., singleton ready flags).

🛏️ 5. Use wait()/notify() when:

✅ You need:

  • A thread to pause until a condition is met
  • Classic producer-consumer logic

❌ Avoid if:

  • You can use Condition, CountDownLatch, or higher-level tools

📌 It’s powerful but tricky — must always be used inside synchronized.

🧰 6. Use java.util.concurrent utilities when:

ToolUse Case
CountDownLatchWait until N threads complete
CyclicBarrierWait until all threads reach a point
SemaphoreLimit concurrent access to a resource
PhaserDynamic coordination across phases
ExchangerSwap data between two threads

📌 Use for coordinating multiple threads with clear rules.

🧰 6. Use java.util.concurrent utilities when:

ToolUse Case
CountDownLatchWait until N threads complete
CyclicBarrierWait until all threads reach a point
SemaphoreLimit concurrent access to a resource
PhaserDynamic coordination across phases
ExchangerSwap data between two threads

📌 Use for coordinating multiple threads with clear rules.

This entry was posted in Без рубрики. Bookmark the permalink.