#Post4 In the previous post(https://lnkd.in/dBEvfvyM), we explored how ConcurrentHashMap achieves thread safety. During that discussion, two important concepts came up: 1. CAS (Compare-And-Swap) 2. Volatile keyword In this post, let’s understand these two concepts in detail. 1. CAS (Compare-And-Swap) CAS is a hardware-level atomic operation used to update a value without using locks. It works using three components: • Memory location → where the value is stored • Expected value → the value we assume is currently present • New value → value to update if expected matches Working: If current value == expected value → update to new value Else → operation fails This makes CAS: • Atomic • Lock-free • Efficient for concurrent systems ABA Problem CAS only checks the current value, not the history. Example: A value changes like this: 10 → 12 → 10 Now CAS sees expected = 10 and current = 10 → it succeeds, even though the value changed in between. This is called the ABA problem. It can be solved using versioning or timestamps (e.g., AtomicStampedReference in Java). 2. Volatile Keyword Volatile is used to ensure visibility across threads. Without volatile: A thread may read a stale value from its local cache. With volatile: Every read gets the latest value from main memory. Example: Thread-1 updates a variable Thread-2 immediately sees the updated value (if volatile is used) How CAS and Volatile Work Together CAS alone is not enough. It needs visibility to work correctly. • Volatile ensures all threads see the latest value • CAS ensures updates happen safely without locking Together, they enable high-performance concurrent systems. Key takeaway CAS → ensures atomic updates without locks Volatile → ensures visibility across threads Together → enable efficient and thread-safe operations (as used in ConcurrentHashMap) In upcoming posts, we will explore these concepts even deeper and understand how threads work internally in Java. #Java #SoftwareEngineering #Multithreading #ConcurrentProgramming #BackendDevelopment #Programming
Understanding CAS and Volatile in Java for Thread Safety
More Relevant Posts
-
𝗢𝗽𝘁𝗶𝗼𝗻𝗮𝗹.𝗼𝗿𝗘𝗹𝘀𝗲() 𝗘𝘅𝗲𝗰𝘂𝘁𝗲𝘀 𝗘𝘃𝗲𝗻 𝗪𝗵𝗲𝗻 𝗩𝗮𝗹𝘂𝗲 𝗣𝗿𝗲𝘀𝗲𝗻𝘁 ⚠️ Looks harmless. It’s not. User user = findUserInCache(userId) .orElse(loadUserFromDatabase(userId)); Many developers read this as: 👉 "load from DB only if cache missed" But that is not what happens. 🔥 What actually happens orElse(...) is eager. That means the argument is evaluated before orElse() is called. So even when user is already present in cache, this still runs: 👉 loadUserFromDatabase(userId) Effectively: User fallback = loadUserFromDatabase(userId); // always executed User user = findUserInCache(userId).orElse(fallback); 💥 Why this hurts in production That fallback is often not cheap. It can be: 🔹 DB query 🔹 remote API call 🔹 disk read 🔹 heavy object construction So what looked like a safe fallback becomes hidden work on every request. 👉 extra CPU 👉 unnecessary IO 👉 more latency 👉 performance regression that is easy to miss in review ✅ The correct approach Use orElseGet(...) when fallback is expensive. User user = findUserInCache(userId) .orElseGet(() -> loadUserFromDatabase(userId)); Now the fallback runs only if Optional is empty. ⚠️ When orElse() is fine orElse() is still okay when the fallback is trivial: String name = maybeName.orElse("unknown"); Constant value, already computed value, or something very cheap. 🧠 Takeaway orElse() is not lazy. If you pass a method call there, that method may execute even when the value is already present. That is exactly the kind of tiny thing that later turns into: "Why is the DB getting hit so much?" 🤦 Have you ever seen a small Java convenience API cause a very non-convenient production problem? 👀 #java #springboot #performance #backend #softwareengineering #programming #coding
To view or add a comment, sign in
-
-
What happens when you're tasked with debugging a legacy codebase that's been untouched for years? I still remember my first encounter with such a project, it was like trying to decipher a puzzle written in a language I barely understood. My team and I were assigned to refactor a massive Java application that had been built over a decade ago. The code was a mess of nested if-else statements, obscure variable names, and outdated libraries. It was overwhelming, to say the least. One particular issue that had me stumped was a tricky null pointer exception that would occur only under certain conditions. I spent hours poring over the code, trying to identify the culprit, until I stumbled upon a hidden gem of a method that was the root cause of the problem. The fix was relatively simple, just a few lines of code: ```java if (object == null) { return Optional.empty(); } else { return Optional.of(object); } ``` This experience taught me the importance of patience, persistence, and attention to detail when working with legacy code. What's the most challenging debugging experience you've had, and how did you overcome it? #DebuggingWarStories #LegacyCode #Java #Refactoring #CodeQuality #SoftwareDevelopment #ProgrammingChallenges #TechJourney
To view or add a comment, sign in
-
Recently revisited an important Java Streams concept: reduce() - one of the most elegant terminal operations for aggregation. Many developers use loops for summing or combining values, but reduce() brings a functional and expressive approach. Example: List<Integer> nums = List.of(1, 2, 3, 4); int sum = nums.stream() .reduce(0, Integer::sum); What happens internally? reduce() repeatedly combines elements: 0 + 1 = 1 1 + 2 = 3 3 + 3 = 6 6 + 4 = 10 Why it matters: ✔ Cleaner than manual loops ✔ Great for immutable / functional style code ✔ Useful for sum, max, min, product, concatenation, custom aggregation ✔ Common in backend processing pipelines Key Insight: Integer::sum is just a method reference for: (a, b) -> a + b Small concepts like this make code more readable and scalable. Still amazed how much depth Java Streams offer beyond just filter() and map(). #Java #Programming #BackendDevelopment #SpringBoot #JavaStreams #Coding #SoftwareEngineering
To view or add a comment, sign in
-
𝗠𝗮𝘀𝘁𝗲𝗿𝗶𝗻𝗴 𝗝𝗮𝘃𝗮’𝘀 𝘃𝗮𝗿 Recently, I explored how Java introduced Local Variable Type Inference (var) in Java 10 and how it transformed the way developers write cleaner and more expressive code. Java has traditionally been known for its verbosity. With the introduction of var through Project Amber, the language took a major step toward modern programming practices—balancing conciseness with strong static typing. 𝗪𝗵𝗮𝘁 𝗜 𝗹𝗲𝗮𝗿𝗻𝗲𝗱: • var allows the compiler to infer types from initializers, reducing boilerplate without losing type safety. • It is not a keyword, but a reserved type name, ensuring backward compatibility. • Works only for local variables, not for fields, method parameters, or return types. • The inferred type is always static and compile-time resolved—no runtime overhead. • Powerful in handling non-denotable types, including anonymous classes and intersection types. Must be used carefully: • Avoid when the type is unclear from the initializer • Prefer when the initializer clearly reveals the type (e.g., constructors or factory methods) • Enhances readability only when the initializer clearly conveys the type. 𝗞𝗲𝘆 𝘁𝗮𝗸𝗲𝗮𝘄𝗮𝘆: var is not just about writing less code—it’s about writing clearer, more maintainable code when used correctly. The real skill lies in knowing when to use it and when not to. A special thanks to Syed Zabi Ulla sir at PW Institute of Innovation for their clear explanations and continuous guidance throughout this topic. #Java #Programming #SoftwareDevelopment #CleanCode #Java10 #Developers #LearningJourney
To view or add a comment, sign in
-
#Post11 In the previous post(https://lnkd.in/dynAvNrN), we saw how to create threads in Java. Now let’s talk about a problem. If creating threads is so simple… why don’t we just create a new thread every time we need one? Let’s say we are building a backend system. For every incoming request/task, we create a new thread: new Thread(() -> { // process request }).start(); This looks simple. But this approach breaks very quickly in real systems because of below mentioned problems. Problem 1: Thread creation is expensive Creating a thread is not just creating an object. It involves: • Allocating memory (stack) • Registering with OS • Scheduling overhead Creating thousands of threads = performance degradation Problem 2: Too many threads → too much context switching We already saw this earlier(https://lnkd.in/dYG3v-vb). More threads does NOT mean more performance. Instead: • CPU spends more time switching • Less time doing actual work Problem 3: No control over thread lifecycle When you create threads manually: • No limit on number of threads • No reuse • Hard to manage failures This quickly becomes difficult to manage as the system grows. So what’s the solution? Instead of creating threads manually: we use something called the Executor Framework. In simple words consider the framework to be like: Earlier, we were manually hiring a worker (thread) for every task. With Executor, we have a team of workers (thread pool), and we just assign tasks to them. Key idea Instead of: Creating a new thread for every task We do: Submit tasks to a pool of reusable threads This is exactly what Java provides using: Executor Framework Key takeaway Manual thread creation works for learning, but does not scale in real-world systems. Thread pools help: • Control number of threads • Reduce overhead • Improve performance We no longer manage threads directly — we delegate that responsibility to the Executor Framework. In the next post, we’ll see how Executor Framework works and how to use it in Java. #Java #Multithreading #Concurrency #BackendDevelopment #SoftwareEngineering
To view or add a comment, sign in
-
💡 𝗝𝗮𝘃𝗮/𝐒𝐩𝐫𝐢𝐧𝐠 𝐁𝐨𝐨𝐭 𝗧𝗶𝗽 - 𝗦𝘄𝗶𝘁𝗰𝗵 𝗘𝘅𝗽𝗿𝗲𝘀𝘀𝗶𝗼𝗻 💎 🕯 𝗧𝗿𝗮𝗱𝗶𝘁𝗶𝗼𝗻𝗮𝗹 𝗦𝘄𝗶𝘁𝗰𝗵 𝗦𝘁𝗮𝘁𝗲𝗺𝗲𝗻𝘁 The traditional switch statement has been part of Java since the beginning. It requires explicit break statements to prevent fall-through, which can lead to bugs if forgotten. Each case must contain statements that execute sequentially, making the code verbose and error-prone. 💡 𝗠𝗼𝗱𝗲𝗿𝗻 𝗦𝘄𝗶𝘁𝗰𝗵 𝗘𝘅𝗽𝗿𝗲𝘀𝘀𝗶𝗼𝗻 Switch expressions were introduced in Java 14 as a more concise and safe alternative. Using the -> syntax, you eliminate the need for break statements and can directly return values. Multiple cases can be grouped with commas, and the compiler enforces exhaustiveness for better safety. ✅ 𝗞𝗲𝘆 𝗕𝗲𝗻𝗲𝗳𝗶𝘁𝘀 ◾ No break statements, safer and cleaner code. ◾ Direct value assignment, treat switch as an expression. ◾ Multiple labels with comma separation. ◾ Compiler exhaustiveness checks, fewer runtime errors. 🤔 Which one do you prefer? #java #springboot #programming #softwareengineering #softwaredevelopment
To view or add a comment, sign in
-
-
𝗝𝗮𝘃𝗮’𝘀 𝗠𝗼𝘀𝘁 𝗔𝗻𝗻𝗼𝘆𝗶𝗻𝗴 𝗢𝘃𝗲𝗿𝗹𝗼𝗮𝗱: List.remove(index) 𝘃𝘀 remove(value) ⚠️ 𝗦𝗮𝗺𝗲 𝗺𝗲𝘁𝗵𝗼𝗱 - 𝗱𝗶𝗳𝗳𝗲𝗿𝗲𝗻𝘁 𝗺𝗲𝗮𝗻𝗶𝗻𝗴 🤯 remove(int index) vs remove(Object o) Tiny type change - different behavior. 𝗪𝗵𝗲𝗿𝗲 𝗶𝘁 𝗯𝗿𝗲𝗮𝗸𝘀 🔥 List<Integer> list = new ArrayList<>(List.of(10,20,30)); list.remove(1); // index -> removes 20 Integer i = 1; list.remove(i); // object -> tries to remove 1 𝗦𝗮𝗺𝗲 𝗻𝘂𝗺𝗯𝗲𝗿. 𝗗𝗶𝗳𝗳𝗲𝗿𝗲𝗻𝘁 𝗿𝗲𝘀𝘂𝗹𝘁 💥 You think index. Java sees object. 𝗡𝗼𝘁 𝗼𝗻𝗹𝘆 𝗹𝗼𝗴𝗶𝗰 - 𝗮𝗹𝘀𝗼 𝗰𝗼𝘀𝘁 🐢 remove(index) - no search remove(value) - extra O(n) lookup 𝗪𝗵𝘆 𝗶𝘁 𝗵𝘂𝗿𝘁𝘀 😤 silent bug same-looking code wrong element or nothing removed 𝗔𝗱𝘃𝗶𝗰𝗲 ✅ Make intent explicit: remove((int) i) or remove(Integer.valueOf(x)) Never rely on overloads in critical paths. #java #backend #softwareengineering #coding #programming #javatips #cleancode #bug #performance
To view or add a comment, sign in
-
-
🚀 Day 540 of #750DaysOfCode 🚀 Today I solved Maximum Non Negative Product in a Matrix (LeetCode 1594) using Java. 🔹 Problem Summary: We are given a matrix where we start from the top-left corner and can move only right or down. Among all possible paths to the bottom-right corner, we must find the maximum non-negative product of the values along the path. If every possible path gives a negative product, we return -1. 🔹 Approach Used (Dynamic Programming): This problem is tricky because the grid contains negative numbers. A negative value can turn the smallest product into the largest, so we must keep track of both: • Maximum product till each cell • Minimum product till each cell For every position, I calculated possible values from the top and left cells and updated both max and min DP tables. At the end, the bottom-right cell gives the answer. 🔹 Key Concepts Learned: ✅ Dynamic Programming on Grid ✅ Handling negative numbers in DP ✅ Keeping both max and min states ✅ Matrix path problems ✅ Modulo handling for large numbers Problems like this show why DP is powerful when greedy approaches fail. #750DaysOfCode #Day540 #LeetCode #Java #DSA #Algorithms #DynamicProgramming #ProblemSolving #CodingChallenge #Consistency
To view or add a comment, sign in
-
-
𝑾𝒉𝒂𝒕 𝒂𝒄𝒕𝒖𝒂𝒍𝒍𝒚 𝒉𝒂𝒑𝒑𝒆𝒏𝒔 𝒘𝒉𝒆𝒏 𝑱𝑽𝑴 𝒓𝒖𝒏𝒔 𝒚𝒐𝒖𝒓 𝑱𝒂𝒗𝒂 𝒑𝒓𝒐𝒈𝒓𝒂𝒎 ? 𝐖𝐞 𝐚𝐥𝐥 𝐰𝐫𝐢𝐭𝐞 "𝐦𝐚𝐢𝐧()" 𝐦𝐞𝐭𝐡𝐨𝐝 𝐁𝐮𝐭 𝐡𝐚𝐯𝐞 𝐲𝐨𝐮 𝐞𝐯𝐞𝐫 𝐭𝐡𝐨𝐮𝐠𝐡𝐭 𝐰𝐡𝐚𝐭 𝐉𝐕𝐌 𝐝𝐨𝐞𝐬 𝐢𝐧𝐭𝐞𝐫𝐧𝐚𝐥𝐥𝐲 𝐭𝐨 𝐬𝐭𝐚𝐫𝐭 𝐲𝐨𝐮𝐫 𝐩𝐫𝐨𝐠𝐫𝐚m ? 🔍 Let’s break it down simply 📝 𝐒𝐭𝐞𝐩-𝐛𝐲-𝐒𝐭𝐞𝐩 𝐄𝐱𝐞𝐜𝐮𝐭𝐢𝐨𝐧 1️⃣ Class Loading ▫️ JVM loads the class into memory 2️⃣ Method Lookup ▫️ JVM looks for exact method signature: 𝐩𝐮𝐛𝐥𝐢𝐜 𝐬𝐭𝐚𝐭𝐢𝐜 𝐯𝐨𝐢𝐝 𝐦𝐚𝐢𝐧(𝐒𝐭𝐫𝐢𝐧𝐠[] 𝐚𝐫𝐠𝐬) ▫️ Signature must match exactly 3️⃣ No Object Creation ▫️JVM does NOT create an object ▫️Because "main()" is static ▫️It is called using class name directly 4️⃣ Method Invocation ▫️ JVM directly calls 5️⃣ Execution Starts ▫️ Program execution begins from "main()" 🧭 𝐈𝐦𝐩𝐨𝐫𝐭𝐚𝐧𝐭 𝐈𝐧𝐬𝐢𝐠𝐡𝐭 "main()" is the entry point of Java program ▫️JVM specifically looks for this method ▫️ If not found → program will not run ❌ 🔁 𝐋𝐨𝐚𝐝 𝐂𝐥𝐚𝐬𝐬 → 𝐅𝐢𝐧𝐝 𝐦𝐚𝐢𝐧() → 𝐂𝐚𝐥𝐥 𝐝𝐢𝐫𝐞𝐜𝐭𝐥𝐲 → 𝐄𝐱𝐞𝐜𝐮𝐭𝐞 ♣️ We write just one method but JVM does a lot behind the scenes to run it. 🎈Did you know this flow before? Or just wrote "main()" without thinking much? Let’s discuss 💬 #Java #JVM #JavaDeveloper #Programming #TechJourney #LearnBySharing #JavaConcepts #InterviewPrep #BackendDevelopment
To view or add a comment, sign in
-
From confusing loops to clean functional code.🧑💻 If you've ever felt tangled in .map(), .filter(), and .collect(), you aren't alone. The Java Stream API is incredibly powerful, but getting the hang of it takes practice. I just uploaded a comprehensive "Stream API: Zero to Hero" PDF. It covers everything from the absolute basics to advanced operations, designed to get you writing functional Java with confidence. Check out the document below, save it for your next coding session, and share it with a fellow developer who might find it useful! 👇 #saffron#saffron 😆 #Java #Programming #BackendDevelopment #StreamAPI #JavaDev #DeveloperCommunity
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