Java.Multithreading.List the principles you follow in multithreaded programming?

✅ 1. Minimize Shared Mutable State

The best way to avoid concurrency issues is not to share data at all.

  • Prefer immutable objects
  • Use thread-local storage when needed
  • Copy-on-write or defensive copying strategies

✅ 2. Prefer High-Level Concurrency Utilities

Don’t reinvent the wheel — Java provides robust tools in java.util.concurrent.

  • Use Executors, ConcurrentHashMap, BlockingQueue, CountDownLatch, etc.
  • Avoid managing Thread manually unless necessary

✅ 3. Use Proper Synchronization

Shared state must be protected using:

  • synchronized blocks or methods
  • ReentrantLock, ReadWriteLock when fine-grained control is needed
  • volatile for simple flags (visibility only, not atomicity)

✅ 4. Avoid Busy Waiting

Avoid loops that burn CPU unnecessarily.

Use:

  • wait()/notify()
  • Condition.await()/signal()
  • LockSupport.park()
  • Semaphore, BlockingQueue, etc.

✅ 5. Keep Critical Sections Short

Reduce lock contention and improve performance by limiting what’s inside a synchronized block.

synchronized (lock) {
    // Only do what absolutely needs locking
}

✅ 6. Use Thread-Safe Collections

Collections like HashMap, ArrayList are not thread-safe by default.

Use:

  • ConcurrentHashMap, CopyOnWriteArrayList, ConcurrentLinkedQueue, etc.

✅ 7. Favor Immutability

Immutable objects require no synchronization — they’re naturally thread-safe.

Great for:

  • Configuration
  • Cache keys
  • Messages passed between threads

✅ 8. Avoid Deadlocks

Deadlocks occur when:

  • Threads wait on locks held by each other
  • Circular waiting + hold and wait

Prevent with:

  • Lock ordering (always acquire locks in the same order)
  • Try using tryLock() with timeout
  • Avoid holding multiple locks if possible

✅ 9. Use Thread Pools, Not New Threads

Creating threads manually is expensive and unscalable.

Use:

  • ExecutorService (for pooled threads)
  • ForkJoinPool (for divide-and-conquer)

✅ 10. Don’t Block in Compute-Heavy Threads

For CPU-bound threads, avoid blocking calls (I/O, sleep, wait).

  • Use dedicated I/O thread pools for blocking ops
  • Consider Reactive / Non-blocking frameworks if needed

✅ 11. Gracefully Handle Shutdown

  • Always call executor.shutdown() or shutdownNow()
  • Use awaitTermination() to block until completion
  • Cleanup resources (e.g., connections, files)

✅ 12. Test with Concurrency in Mind

Bugs may only appear under specific interleaving of threads

Use:

  • Tools like jUnit + awaitility, Stress tests
  • Simulators like jcstress
  • Thread.sleep() to simulate timing issues (during tests only!)

🔥 Bonus: Golden Rules for Multithreaded Design

RuleSummary
🧠 Design for SimplicitySimpler code = fewer threading bugs
Don’t guess, measureProfile, stress test, use thread dumps
🧪 Test like it’s productionAssume worst-case scheduling
🛠 Favor stateless or functional designEasier to parallelize and test
This entry was posted in Без рубрики. Bookmark the permalink.