Most concurrency bugs are not because of threads… they’re because of shared mutable state. 🚨 One thing that has saved me multiple times in Java: Immutability. In multi-threaded applications, multiple threads accessing the same object can easily lead to: → Race conditions → Inconsistent data → Hard-to-debug production issues The simplest way to avoid this? Don’t allow the data to change. What I follow 👇 ✔ Use immutable objects wherever possible ✔ Make fields final ✔ Avoid setters for shared data ✔ Prefer returning new objects instead of modifying existing ones Why this works: Immutable objects are inherently thread-safe. No locks. No synchronization. No surprises. In real systems, this reduces a huge class of bugs without adding complexity. Sometimes the best concurrency solution… is not writing concurrent code at all. Do you actively use immutability in your designs? 👇 #Java #Multithreading #Concurrency #BackendDevelopment #SoftwareEngineering #CleanCode
Avoiding Concurrency Bugs with Immutability in Java
More Relevant Posts
-
I used to think synchronized was enough for handling multithreading. Until I needed more control. 👉 Problem: In real-world backend systems, basic locking isn’t always flexible enough. ❌ With synchronized: No control over lock acquisition Threads can block indefinitely No way to interrupt waiting threads 👉 Then I discovered ReentrantLock ✅ Why it’s more powerful: ✔️ tryLock() → avoids waiting forever ✔️ lockInterruptibly() → can stop waiting threads ✔️ Fairness option → prevents thread starvation ✔️ More control over locking/unlocking 🧠 Real-world use: High-concurrency systems Complex locking scenarios When you need timeout-based locking 💡 Simple thought: synchronized = simple & automatic ReentrantLock = flexible & powerful 💬 Curious: Have you ever needed more control than synchronized provides? #Java #Multithreading #Backend #SystemDesign #Concurrency #LearningInPublic
To view or add a comment, sign in
-
Day 65/100: Today I took another topic of LLD i.e. #Concurrency. Concurrency is nothing but dealing with multiple things at the same time. Every modern software system deals with concurrency. Your phone runs dozens of apps simultaneously. A web server handles thousands of requests at once. In Golang we can achieve concurrency using goroutines whereas in other programming languages like java we have multithreading concept for concurrency. When we talking about concurrency there is always confusion between concurrency and parallelism. Concurrency is about organizing code to handle many tasks in overlapping time periods. Parallelism involves performing multiple tasks at the same exact time, usually on different CPU cores. In concurrency we have to discover some important terms related to it. Race condition: A race condition occurs when the behavior of a program depends on the relative timing of events, such as the order in which threads are scheduled. When two or more threads access shared data concurrently, and at least one modifies it, the final result depends on who "wins the race" to access the data first. Deadlock: A deadlock is a state where a set of threads is blocked because each thread is holding a resource and waiting for a resource held by another thread in the set. Mutex: Mutex is a synchronization primitive that provides mutual exclusion. When a thread acquires (locks) a mutex, any other thread that tries to acquire the same mutex will block until the first thread releases (unlocks) it. The thread that locks must be the one to unlock. Concurrency Patterns: Thread Pool Pattern Producer-Consumer Pattern Fork-Join Pattern FanIn/out Pattern Time to do it again tomorrow :) #systemdesign #100daysofcode #softwareengineering #consistency
To view or add a comment, sign in
-
The hardest part of concurrency is not running things in parallel. It is deciding what to do while things are still running. We had a flow where some results came back early, some were slow, and some were optional. But everything was treated like one flat batch. That was the mistake. What we missed was that not all concurrent work has the same shape. - Some work is critical. - Some can fail quietly. - Some should finish early and unblock the rest. Structured concurrency helped me think about this differently. Not just as "run these tasks together", but as “give this work a clearer lifecycle and clearer ownership.” One principle that stuck with me: if work has different responsibilities, it probably should not live in the same scope. https://lnkd.in/gBTdjKeV #Java #SystemDesign #Concurrency
To view or add a comment, sign in
-
While building a recent Spring Boot application, I realized... The Hook: Stop defaulting to .parallelStream() to make your Java code "faster." 🛑 The Insight: It’s a common misconception that parallel streams always improve performance. Under the hood, parallelStream() uses the common ForkJoinPool. If you are executing CPU-intensive tasks on a massive dataset, it’s great. But if you are doing I/O operations (like database calls or network requests) inside that stream, you will exhaust the thread pool and bottleneck your entire application. The Pro Tip: Always benchmark. For I/O bound tasks, look into asynchronous programming (like CompletableFuture) or Java 21's Virtual Threads instead of parallel streams. #Java #PerformanceOptimization #SoftwareEngineering #CleanCode
To view or add a comment, sign in
-
Continuing my recent posts on JVM internals and performance, today I’m sharing a look at Java 21 Virtual Threads (from Project Loom). For a long time, Java handled concurrency using platform threads (OS threads)—which are powerful but expensive, especially for I/O-heavy applications. This led to complex patterns like thread pools, async programming, and reactive frameworks to achieve scalability. With Virtual Threads, Java introduces a lightweight threading model where thousands (even millions) of threads can be managed efficiently. 👉 When a virtual thread performs a blocking I/O operation, the underlying carrier (platform) thread is released to do other work. This brings Java closer to the efficiency of event-loop models (like in Node.js), while still allowing developers to write simple, synchronous code without callback-heavy complexity. However, in real-world scenarios, especially when teams migrate from Java 8/11 to Java 21, it’s important to keep a few things in mind: • Virtual Threads are not a silver bullet—they primarily improve I/O-bound workloads, not CPU-bound ones • If the architecture is not aligned, you may not see significant latency improvements • Legacy codebases often contain synchronized blocks or locking, which can lead to thread pinning and reduce the benefits of Virtual Threads Project Loom took years to evolve because it required deep changes to the JVM, scheduling, and thread management—while preserving backward compatibility and Java’s simplicity. Sharing a diagram that illustrates: • Platform threads vs Virtual Threads • Carrier thread behavior • Pinning scenarios Curious to hear—are you exploring Virtual Threads in your applications, or still evaluating? 👇 #Java #Java21 #VirtualThreads #ProjectLoom #Concurrency #Performance #SoftwareEngineering
To view or add a comment, sign in
-
-
🚨 Deadlocks in Virtual Threads — Myth vs Reality (Java) With the rise of **** and virtual threads in ****, many developers assume concurrency problems like deadlocks are “handled automatically.” 👉 Let’s clear the confusion. --- ❗ Do Virtual Threads Prevent Deadlocks? No. They don’t. Virtual threads: ✔ Make concurrency lightweight ✔ Improve scalability ❌ Do NOT eliminate deadlocks A deadlock is still a logical problem, not a thread-type problem. --- 🔍 What actually happens? Even with virtual threads: - If Thread A holds Lock 1 and waits for Lock 2 - Thread B holds Lock 2 and waits for Lock 1 💥 You still get a deadlock. Virtual threads are scheduled by the JVM, but locks behave the same way as with platform threads. --- ⚙️ So how does Java handle it? Java doesn’t “fix” deadlocks automatically — instead, it provides tools to detect and debug them: 🧠 Thread Dump Analysis - Use "jstack" or JVM tools to identify blocked threads 🧠 ThreadMXBean - Programmatically detect deadlocks 🧠 Structured Concurrency (Loom feature) - Helps reduce complexity, but not a guarantee --- 🧩 What changes with Virtual Threads? Here’s the key shift: 👉 Blocking is cheap, but bad locking design is still expensive Virtual threads: - Reduce thread starvation - Allow millions of threads - But can still get stuck if locks are misused --- ✅ Best Practices to Avoid Deadlocks ✔ Always acquire locks in a fixed order ✔ Prefer tryLock() with timeout over synchronized blocks ✔ Minimize shared mutable state ✔ Use higher-level concurrency utilities (Executors, Futures) ✔ Embrace immutable design --- 💡 Final Thought «Virtual threads solve scalability problems, not design problems» If your locking strategy is flawed, even millions of lightweight threads won’t save you. --- #Java #VirtualThreads #ProjectLoom #Concurrency #BackendEngineering #SoftwareDesign
To view or add a comment, sign in
-
A lot of Java devs solve thread-safety issues with one keyword: synchronized. And honestly, sometimes that’s the right call. Simple, readable, gets the job done. But I’ve seen codebases where synchronized is used everywhere, and once traffic grows, performance starts falling apart. What happens? Only one thread can enter that block/method at a time. If 50 requests hit it together: 1 executes 49 wait So even if your app server has resources, requests are still lining up behind one lock. Where it gets ugly When slow work is inside the lock: -DB queries -External API calls -File operations -Heavy loops / processing Now threads aren’t waiting for CPU. They’re waiting because one thread is holding a lock during slow operations. That’s where response times spike. Better approach depends on the case Use ReentrantLock if you need more control: -tryLock() -timeout -fairness -interruptible waits Use concurrent collections like ConcurrentHashMap instead of manually synchronizing shared maps/lists. Don’t lock the whole method if only one small state update needs protection. Use AtomicInteger / AtomicLong for counters instead of full locks. Real takeaway Thread safety matters. But making everything synchronized is not a concurrency strategy. First make it correct. Then make it scale. #Java #Concurrency #Multithreading #BackendDevelopment #Performance #SoftwareEngineering
To view or add a comment, sign in
-
𝐓𝐡𝐫𝐞𝐚𝐝 𝐒𝐚𝐟𝐞𝐭𝐲 - 𝐭𝐡𝐞 𝐛𝐮𝐠 𝐭𝐡𝐚𝐭 𝐥𝐢𝐞𝐬 𝐪𝐮𝐢𝐞𝐭𝐥𝐲 𝐮𝐧𝐭𝐢𝐥 𝐩𝐞𝐚𝐤 𝐭𝐫𝐚𝐟𝐟𝐢𝐜. Multiple threads sharing the same memory is powerful. It is also dangerous. 𝐖𝐡𝐚𝐭 𝐢𝐬 𝐢𝐭? When two threads read and write the same variable at the same time the result becomes unpredictable. This is called a Race Condition. No crash. No exception. Just silently wrong results. A payment processed twice. A counter off by thousands. A balance that never adds up. 𝐖𝐡𝐞𝐧 𝐝𝐨𝐞𝐬 𝐢𝐭 𝐡𝐚𝐩𝐩𝐞𝐧? → Shared counters updated by multiple threads → Shared collections read and written simultaneously → Singleton beans with mutable state in Spring → Cached values updated without synchronization 𝐇𝐨𝐰 𝐭𝐨 𝐩𝐫𝐞𝐯𝐞𝐧𝐭 𝐢𝐭? → Use Atomic types for simple counters and flags → Use immutable objects wherever possible → Use thread-safe collections like ConcurrentHashMap → Avoid shared mutable state entirely when you can → Scope variables locally - local variables are always safe 𝐓𝐡𝐞 𝐦𝐢𝐧𝐝𝐬𝐞𝐭 𝐬𝐡𝐢𝐟𝐭: Stop asking "does this work?" Start asking "what happens when 1000 threads hit this simultaneously?" Thread safety bugs don't show in unit tests. They show in production at the worst possible moment. #Java #ThreadSafety #Concurrency #RaceCondition #BackendEngineering
To view or add a comment, sign in
-
"Architecting Knowledge" - Java Wisdom Series Post #17: Virtual Threads - Rethinking Concurrency 👇 Million threads. One JVM. Welcome to Project Loom. Why This Matters: Platform threads map 1:1 to OS threads - each consumes ~1MB stack memory. You can create maybe 4000-10000 before your JVM dies. Virtual threads are JVM-managed and stack memory is allocated dynamically on heap - you can create millions. When a virtual thread blocks on I/O, the JVM unmounts it from its carrier thread (platform thread), letting that carrier run other virtual threads. This makes blocking I/O efficient again - no more callback hell. BUT beware thread pinning: synchronized blocks prevent unmounting in Java 21-23 (fixed in 24). Use ReentrantLock for long blocking operations. Key Takeaway: Virtual threads aren't faster - they're cheaper and more scalable. Perfect for I/O-bound workloads (web servers, microservices, API calls). Don't pool them, don't cache in ThreadLocal aggressively. Write simple blocking code, let Loom handle concurrency. #Java #JavaWisdom #VirtualThreads #ProjectLoom #Concurrency #Java21 Are you still using thread pools for I/O-bound tasks? Time to go virtual! All code examples on GitHub - bookmark for quick reference: https://lnkd.in/dJUx3Rd3
To view or add a comment, sign in
-
-
Virtual Threads in Java 21 for Scalable Backend Engineering. We dive into how Java 21’s Virtual Threads eliminate the complexity of traditional thread pools, letting you handle massive concurrency with simple, readable code, perfect for production AI and high-traffic backend systems. This is the kind of modern, performance-first upgrade every serious backend engineer needs in 2026. Watch the full clip below and comment: Have you started using Virtual Threads in your projects yet? Full Video: https://lnkd.in/e7rpe5q4 #Java21 #VirtualThreads #AIBackendEngineering #MasteringBackend
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development