{"id":6153,"date":"2023-11-01T17:04:00","date_gmt":"2023-11-02T00:04:00","guid":{"rendered":"https:\/\/ioflood.com\/blog\/?p=6153"},"modified":"2024-03-04T14:55:06","modified_gmt":"2024-03-04T21:55:06","slug":"java-volatile","status":"publish","type":"post","link":"https:\/\/ioflood.com\/blog\/java-volatile\/","title":{"rendered":"Java&#8217;s Volatile Keyword: Usage and Best Practices"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"alignright size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/ioflood.com\/blog\/wp-content\/uploads\/2023\/11\/java_volatile_keyword_processor_chip_glowing-300x300.jpg\" alt=\"java_volatile_keyword_processor_chip_glowing\" width=\"300\" height=\"300\" title=\"\"><\/figure>\n<\/div>\n<p>Are you finding the volatile keyword in Java a bit confusing? You&#8217;re not alone. Many developers find themselves puzzled when it comes to handling volatile in Java, but we&#8217;re here to help.<\/p>\n<p>Think of the volatile keyword in Java as a traffic controller &#8211; ensuring smooth flow of data in multithreaded environments. It&#8217;s a powerful tool that helps maintain consistency across different threads.<\/p>\n<p><strong>In this guide, we&#8217;ll walk you through the process of understanding and using the volatile keyword in Java<\/strong>, from the basics to more advanced techniques. We&#8217;ll cover everything from simple usage of volatile to its role in Java&#8217;s multithreading and memory visibility.<\/p>\n<p>Let&#8217;s dive in and start mastering the volatile keyword in Java!<\/p>\n<h2>TL;DR: What is the Volatile Keyword in Java?<\/h2>\n<blockquote><p>\n  The <code>volatile<\/code> keyword in Java is used to indicate that a variable&#8217;s value can be modified by different threads.Used with the syntax, <code>volatile dataType variableName = x;<\/code> It ensures that changes made to a volatile variable by one thread are immediately visible to other threads.\n<\/p><\/blockquote>\n<p>Here&#8217;s a simple example:<\/p>\n<pre><code class=\"language-java line-numbers\">volatile int count = 0;\n<\/code><\/pre>\n<p>In this example, we declare a variable <code>count<\/code> as <code>volatile<\/code>. This means that if one thread modifies <code>count<\/code>, the change will be immediately visible to all other threads.<\/p>\n<blockquote><p>\n  This is a basic usage of the volatile keyword in Java, but there&#8217;s much more to learn about it, especially in the context of multithreading. Continue reading for more detailed information and advanced usage scenarios.\n<\/p><\/blockquote>\n<h2>Understanding the Basics: Java Volatile Keyword<\/h2>\n<p>The <code>volatile<\/code> keyword in Java is a type of variable modifier that tells the JVM (Java Virtual Machine) that a variable can be accessed and modified by multiple threads. The <code>volatile<\/code> keyword is used in multithreaded environments to ensure that changes made to a variable by one thread are immediately visible to other threads.<\/p>\n<p>Let&#8217;s take a look at a basic example:<\/p>\n<pre><code class=\"language-java line-numbers\">public class VolatileExample {\n    private volatile int count = 0;\n\n    public void incrementCount() {\n        count++;\n    }\n\n    public void displayCount() {\n        System.out.println(\"Count: \" + count);\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        VolatileExample example = new VolatileExample();\n        example.incrementCount();\n        example.displayCount();\n    }\n}\n\n# Output:\n# Count: 1\n<\/code><\/pre>\n<p>In this example, we have a <code>VolatileExample<\/code> class with a <code>volatile<\/code> integer <code>count<\/code>. The <code>incrementCount()<\/code> method increments the <code>count<\/code>, and the <code>displayCount()<\/code> method displays the current value of <code>count<\/code>. When we run the <code>main<\/code> method, it creates an instance of <code>VolatileExample<\/code>, calls <code>incrementCount()<\/code>, and then calls <code>displayCount()<\/code>. The output shows the updated value of <code>count<\/code>.<\/p>\n<p>The <code>volatile<\/code> keyword ensures that the updated value of <code>count<\/code> is immediately visible to all threads. If <code>count<\/code> was not declared as <code>volatile<\/code>, there could be a delay in visibility of the updated value to other threads, leading to inconsistent results.<\/p>\n<h3>Advantages and Pitfalls of Volatile Keyword<\/h3>\n<p>The primary advantage of the <code>volatile<\/code> keyword is its guarantee of visibility of changes across threads. It ensures that a change in a <code>volatile<\/code> variable in one thread is immediately reflected in all other threads.<\/p>\n<p>However, the <code>volatile<\/code> keyword does not guarantee atomicity. For example, the increment operation (<code>count++<\/code>) in the above code is not atomic. It involves multiple steps &#8211; reading the current value of <code>count<\/code>, incrementing it, and then writing the updated value back to <code>count<\/code>. These steps are not performed as a single, indivisible operation. Therefore, in a multithreaded environment, it&#8217;s possible for another thread to modify <code>count<\/code> between these steps, leading to unexpected results.<\/p>\n<p>To ensure atomicity in such cases, other mechanisms like synchronization or atomic variables may be required, which we will explore in the advanced and expert sections.<\/p>\n<h2>The Volatile Keyword in Multithreading<\/h2>\n<p>The <code>volatile<\/code> keyword in Java becomes particularly important in a multithreaded environment. It ensures that changes made to a <code>volatile<\/code> variable by one thread are immediately visible to all other threads, which is crucial for maintaining data consistency in multithreading.<\/p>\n<p>Let&#8217;s explore an example to illustrate this:<\/p>\n<pre><code class=\"language-java line-numbers\">public class VolatileExample extends Thread {\n    private volatile boolean running = true;\n\n    public void run() {\n        while (running) {\n            System.out.println(\"Running\");\n        }\n    }\n\n    public void stopRunning() {\n        running = false;\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) throws InterruptedException {\n        VolatileExample example = new VolatileExample();\n        example.start();\n\n        \/\/ Sleep for 1 second\n        Thread.sleep(1000);\n\n        example.stopRunning();\n    }\n}\n\n# Output:\n# Running...\n# (After 1 second)\n# (No more output, thread stops)\n<\/code><\/pre>\n<p>In this example, <code>VolatileExample<\/code> is a thread that runs a loop as long as <code>running<\/code> is <code>true<\/code>. The <code>stopRunning()<\/code> method sets <code>running<\/code> to <code>false<\/code>, which should stop the loop.<\/p>\n<p>In the <code>main<\/code> method, we start the <code>VolatileExample<\/code> thread, wait for 1 second, and then call <code>stopRunning()<\/code>. Because <code>running<\/code> is <code>volatile<\/code>, the change is immediately visible to the <code>VolatileExample<\/code> thread, and it stops running.<\/p>\n<p>If <code>running<\/code> was not <code>volatile<\/code>, there&#8217;s a chance that the <code>VolatileExample<\/code> thread might not see the updated value immediately due to caching, and it could continue running longer than expected.<\/p>\n<h3>Volatile and Memory Visibility<\/h3>\n<p>The <code>volatile<\/code> keyword also plays a crucial role in memory visibility. In Java, each thread has its own stack, and it can also access the heap. The heap contains objects and instance variables, but local variables are stored in the thread&#8217;s stack and are not visible to other threads.<\/p>\n<p>However, when a variable is declared <code>volatile<\/code>, it ensures that the value of the <code>volatile<\/code> variable is always read from and written to the main memory, and not from the thread&#8217;s local cache. This ensures that the most recent value of the <code>volatile<\/code> variable is always visible to all threads, which is crucial for maintaining data consistency in multithreading.<\/p>\n<h3>Best Practices for Using Volatile<\/h3>\n<p>While the <code>volatile<\/code> keyword is a powerful tool for controlling memory visibility and consistency in multithreading, it&#8217;s important to use it judiciously. Overuse of <code>volatile<\/code> can lead to performance issues, as it requires frequent reading from and writing to the main memory.<\/p>\n<p>Furthermore, <code>volatile<\/code> should not be used in place of proper synchronization. While it ensures visibility of changes across threads, it does not guarantee atomicity of compound operations. For compound operations, other synchronization mechanisms may be required.<\/p>\n<h2>Exploring Alternatives: Synchronized Blocks and Atomic Classes<\/h2>\n<p>While the <code>volatile<\/code> keyword is a powerful tool for ensuring memory visibility across threads, it does not guarantee atomicity for compound operations. In such scenarios, we need to consider alternative approaches to achieve thread safety. Two such alternatives are using <code>synchronized<\/code> blocks and atomic classes.<\/p>\n<h3>Synchronized Blocks for Thread Safety<\/h3>\n<p>A <code>synchronized<\/code> block in Java is used to mark a method or a block of code as synchronized. A synchronized block can only be accessed by one thread at a time, ensuring thread safety for critical sections of code.<\/p>\n<p>Let&#8217;s look at an example:<\/p>\n<pre><code class=\"language-java line-numbers\">public class SynchronizedExample {\n    private int count = 0;\n\n    public synchronized void incrementCount() {\n        count++;\n    }\n\n    public void displayCount() {\n        System.out.println(\"Count: \" + count);\n    }\n}\n\n# Output:\n# Count: 1\n<\/code><\/pre>\n<p>In this example, the <code>incrementCount()<\/code> method is declared as <code>synchronized<\/code>. This means that if multiple threads call <code>incrementCount()<\/code>, they will do so one at a time. This ensures that the increment operation is atomic and thread-safe.<\/p>\n<h3>Atomic Classes for Atomic Operations<\/h3>\n<p>Java provides a set of atomic classes in the <code>java.util.concurrent.atomic<\/code> package for performing atomic operations. These classes use efficient machine-level instructions to ensure atomicity, instead of locking.<\/p>\n<p>Here&#8217;s an example using <code>AtomicInteger<\/code>:<\/p>\n<pre><code class=\"language-java line-numbers\">import java.util.concurrent.atomic.AtomicInteger;\n\npublic class AtomicExample {\n    private AtomicInteger count = new AtomicInteger(0);\n\n    public void incrementCount() {\n        count.incrementAndGet();\n    }\n\n    public void displayCount() {\n        System.out.println(\"Count: \" + count);\n    }\n}\n\n# Output:\n# Count: 1\n<\/code><\/pre>\n<p>In this example, <code>count<\/code> is an <code>AtomicInteger<\/code>. The <code>incrementAndGet()<\/code> method increments <code>count<\/code> atomically, ensuring that the operation is thread-safe even without using <code>synchronized<\/code>.<\/p>\n<h3>Comparison and Recommendations<\/h3>\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>Advantages<\/th>\n<th>Disadvantages<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>volatile<\/code><\/td>\n<td>Ensures visibility of changes across threads.<\/td>\n<td>Does not guarantee atomicity for compound operations.<\/td>\n<\/tr>\n<tr>\n<td><code>synchronized<\/code><\/td>\n<td>Ensures atomicity for compound operations.<\/td>\n<td>Can lead to thread blocking and decreased performance.<\/td>\n<\/tr>\n<tr>\n<td>Atomic classes<\/td>\n<td>Ensures atomicity for specific operations without locking.<\/td>\n<td>Limited to specific operations provided by atomic classes.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>While <code>volatile<\/code> is useful for ensuring memory visibility, it does not guarantee atomicity for compound operations. On the other hand, <code>synchronized<\/code> blocks can ensure atomicity but may lead to performance issues due to thread blocking. Atomic classes provide a middle ground by ensuring atomicity for specific operations without locking, but their use is limited to the operations provided by the classes.<\/p>\n<p>Therefore, the choice between <code>volatile<\/code>, <code>synchronized<\/code>, and atomic classes depends on the specific requirements of your code. Understanding the nuances of each method is key to writing efficient and thread-safe Java code.<\/p>\n<h2>Troubleshooting Common Issues with Java&#8217;s Volatile Keyword<\/h2>\n<p>While the <code>volatile<\/code> keyword in Java can be a powerful tool for ensuring memory visibility across threads, there are several common issues and considerations to keep in mind.<\/p>\n<h3>Visibility Issues<\/h3>\n<p>One of the main purposes of the <code>volatile<\/code> keyword is to ensure that changes to a variable are immediately visible to all threads. However, this only applies to the specific <code>volatile<\/code> variable. If you have multiple variables that depend on each other, you may still encounter visibility issues.<\/p>\n<p>For instance, consider this example:<\/p>\n<pre><code class=\"language-java line-numbers\">volatile boolean flag = false;\nint count = 0;\n\npublic void incrementCount() {\n    if (!flag) {\n        count++;\n        flag = true;\n    }\n}\n\n# Output:\n# (Depends on the thread execution, may not be as expected)\n<\/code><\/pre>\n<p>In this code, <code>count<\/code> is incremented if <code>flag<\/code> is <code>false<\/code>. Then <code>flag<\/code> is set to <code>true<\/code>. However, because <code>count<\/code> is not <code>volatile<\/code>, changes to <code>count<\/code> may not be immediately visible to other threads, leading to inconsistent results.<\/p>\n<h3>Atomicity Problems<\/h3>\n<p>The <code>volatile<\/code> keyword does not guarantee atomicity for compound operations. A compound operation, such as <code>count++<\/code>, involves multiple steps that are not performed atomically.<\/p>\n<p>Consider this example:<\/p>\n<pre><code class=\"language-java line-numbers\">volatile int count = 0;\n\npublic void incrementCount() {\n    count++;\n}\n\n# Output:\n# (Depends on the thread execution, may not be as expected)\n<\/code><\/pre>\n<p>In this code, multiple threads calling <code>incrementCount()<\/code> may lead to unexpected results, because the increment operation is not atomic.<\/p>\n<h3>Solutions and Workarounds<\/h3>\n<p>To resolve visibility issues with multiple variables, consider using a <code>synchronized<\/code> block or an atomic class that can ensure atomicity and visibility for compound operations.<\/p>\n<p>To resolve atomicity problems with <code>volatile<\/code> variables, consider using <code>synchronized<\/code> blocks or atomic classes. For instance, <code>AtomicInteger<\/code> can be used to perform atomic increment operations.<\/p>\n<p>By being aware of these common issues and considerations, you can use the <code>volatile<\/code> keyword effectively and write thread-safe Java code.<\/p>\n<h2>Java Memory Model, Thread Safety, and Synchronization<\/h2>\n<p>To fully grasp the <code>volatile<\/code> keyword in Java, it&#8217;s essential to understand some fundamental concepts: Java&#8217;s memory model, thread safety, and synchronization.<\/p>\n<h3>Java&#8217;s Memory Model<\/h3>\n<p>In Java, memory is divided into two main areas: the heap and the stack. Each thread in Java has its own stack, which contains local variables and references to objects in the heap. The heap is a shared memory area where all objects are stored.<\/p>\n<pre><code class=\"language-java line-numbers\">public class MemoryModelExample {\n    int heapVariable = 0;  \/\/ Stored in the heap\n\n    public void method() {\n        int stackVariable = 0;  \/\/ Stored in the stack\n    }\n}\n\n# Output:\n# (No output, just an example of variables in the heap and stack)\n<\/code><\/pre>\n<p>In this example, <code>heapVariable<\/code> is an instance variable that&#8217;s stored in the heap, while <code>stackVariable<\/code> is a local variable that&#8217;s stored in the thread&#8217;s stack.<\/p>\n<p>Java&#8217;s memory model dictates how and when changes to variables are visible to other threads. The <code>volatile<\/code> keyword plays a crucial role in this, ensuring that changes to a <code>volatile<\/code> variable are immediately visible to all threads.<\/p>\n<h3>Thread Safety in Java<\/h3>\n<p>Thread safety is a concept in multithreading that ensures that shared data is accessed in a manner that doesn&#8217;t cause inconsistencies or errors. The <code>volatile<\/code> keyword is a tool for achieving thread safety by ensuring that changes to a <code>volatile<\/code> variable are immediately visible to all threads.<\/p>\n<h3>Synchronization in Java<\/h3>\n<p>Synchronization is a mechanism that controls the access of multiple threads to shared resources. In Java, synchronization can be achieved using <code>synchronized<\/code> blocks or methods, which allow only one thread to access the synchronized code at a time.<\/p>\n<pre><code class=\"language-java line-numbers\">public class SynchronizationExample {\n    private int count = 0;\n\n    public synchronized void incrementCount() {\n        count++;\n    }\n}\n\n# Output:\n# (No output, just an example of a synchronized method)\n<\/code><\/pre>\n<p>In this example, the <code>incrementCount()<\/code> method is <code>synchronized<\/code>, which means that if multiple threads call this method, they will do so one at a time. This ensures that the increment operation is atomic and thread-safe.<\/p>\n<p>Understanding these fundamentals provides the groundwork for understanding the <code>volatile<\/code> keyword in Java and its role in multithreading and memory visibility.<\/p>\n<h2>Java&#8217;s Volatile Keyword in Large-Scale Applications<\/h2>\n<p>The <code>volatile<\/code> keyword is not just a concept for academic discussion; it&#8217;s a practical tool that plays a significant role in large-scale, multithreaded applications. By ensuring that changes to a <code>volatile<\/code> variable are immediately visible to all threads, it helps maintain data consistency in complex multithreaded environments.<\/p>\n<p>Consider a large-scale application that processes millions of transactions per day. Such an application would likely involve multiple threads working on shared data. In such a scenario, the <code>volatile<\/code> keyword can be crucial for ensuring that all threads see the most recent data and maintain consistency.<\/p>\n<h2>Exploring Related Concepts<\/h2>\n<p>If you&#8217;re interested in going beyond the <code>volatile<\/code> keyword, there are several related concepts that you might find interesting. For instance, Java&#8217;s Concurrency API provides a high-level framework for handling multithreading, including thread pools, futures, and callable tasks.<\/p>\n<p>Locks in Java are another powerful tool for controlling access to shared resources in a multithreaded environment. Unlike the <code>volatile<\/code> keyword, which is a variable modifier, locks can be used to control access to blocks of code, ensuring that only one thread can execute the code at a time.<\/p>\n<h2>Further Resources for Mastering Java&#8217;s Volatile Keyword<\/h2>\n<p>If you wish to delve deeper into the topic of <code>volatile<\/code> keyword in Java and related concepts, here are some resources that you might find helpful:<\/p>\n<ul>\n<li><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/ioflood.com\/blog\/keywords-of-java\/\">Tips and Techniques for Using Java Keywords<\/a> &#8211; Explore the role of reserved words like &#8220;const&#8221; and &#8220;goto&#8221; in Java language.<\/p>\n<\/li>\n<li>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/ioflood.com\/blog\/implements-java\/\"><code>implements<\/code> Keyword in Java<\/a> &#8211; Explore the &#8216;implements&#8217; keyword in Java for implementing interfaces and more.<\/p>\n<\/li>\n<li>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/ioflood.com\/blog\/java-record\/\">Exploring Java Records<\/a> &#8211; Learn how Java record simplifies the creation of data transfer objects (DTOs).<\/p>\n<\/li>\n<li>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/jcip.net\/\" target=\"_blank\" rel=\"noopener\">Java Concurrency in Practice<\/a> covers all aspects of concurrency in Java, including the <code>volatile<\/code> keyword.<\/p>\n<\/li>\n<li>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/www.amazon.com\/Java-Beginners-Guide-Herbert-Schildt\/dp\/0071809252\" target=\"_blank\" rel=\"noopener\">Java: A Beginner&#8217;s Guide<\/a> provides a solid foundation in Java programming.<\/p>\n<\/li>\n<li>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/docs.oracle.com\/javase\/tutorial\/essential\/concurrency\/\" target=\"_blank\" rel=\"noopener\">Oracle&#8217;s Java Tutorials: Concurrency<\/a> covers the <code>volatile<\/code> keyword and other related concepts.<\/p>\n<\/li>\n<\/ul>\n<p>By exploring these resources and practicing with real-world examples, you can master the <code>volatile<\/code> keyword in Java and write efficient, thread-safe code.<\/p>\n<h2>Wrapping Up: Mastering the Volatile Keyword in Java<\/h2>\n<p>In this comprehensive guide, we&#8217;ve explored the <code>volatile<\/code> keyword in Java, a unique tool for ensuring memory visibility across threads in multithreaded environments.<\/p>\n<p>We began with the basics, understanding how the <code>volatile<\/code> keyword works and its role in Java. We then delved into more advanced usage, such as its application in multithreading and memory visibility. We also addressed common issues that you might encounter when using the <code>volatile<\/code> keyword, such as visibility issues and atomicity problems, and provided solutions and workarounds for each issue.<\/p>\n<p>We also discovered alternative approaches to achieving thread safety, such as using <code>synchronized<\/code> blocks and atomic classes. These alternatives provide additional tools for handling more complex scenarios where <code>volatile<\/code> might not be sufficient.<\/p>\n<p>Here&#8217;s a quick comparison of the methods we&#8217;ve discussed:<\/p>\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>Advantages<\/th>\n<th>Disadvantages<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>volatile<\/code><\/td>\n<td>Ensures visibility of changes across threads.<\/td>\n<td>Does not guarantee atomicity for compound operations.<\/td>\n<\/tr>\n<tr>\n<td><code>synchronized<\/code><\/td>\n<td>Ensures atomicity for compound operations.<\/td>\n<td>Can lead to thread blocking and decreased performance.<\/td>\n<\/tr>\n<tr>\n<td>Atomic classes<\/td>\n<td>Ensures atomicity for specific operations without locking.<\/td>\n<td>Limited to specific operations provided by atomic classes.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Whether you&#8217;re just starting out with Java&#8217;s <code>volatile<\/code> keyword or looking to deepen your understanding, we hope this guide has helped you navigate its nuances and applications.<\/p>\n<p>The ability to ensure memory visibility and data consistency across threads is a powerful tool in any Java developer&#8217;s toolkit. With the knowledge you&#8217;ve gained from this guide, you&#8217;re well equipped to use the <code>volatile<\/code> keyword effectively in your Java programs. Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Are you finding the volatile keyword in Java a bit confusing? You&#8217;re not alone. Many developers find themselves puzzled when it comes to handling volatile in Java, but we&#8217;re here to help. Think of the volatile keyword in Java as a traffic controller &#8211; ensuring smooth flow of data in multithreaded environments. It&#8217;s a powerful [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":7320,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[154,121],"tags":[],"class_list":["post-6153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","category-programming-coding","cat-154-id","cat-121-id","has_thumb"],"_links":{"self":[{"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/posts\/6153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/comments?post=6153"}],"version-history":[{"count":10,"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/posts\/6153\/revisions"}],"predecessor-version":[{"id":17955,"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/posts\/6153\/revisions\/17955"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/media\/7320"}],"wp:attachment":[{"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/media?parent=6153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/categories?post=6153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ioflood.com\/blog\/wp-json\/wp\/v2\/tags?post=6153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}