DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Recurrent Workflows With Cloud Native Dapr Jobs
  • Avoiding If-Else: Advanced Approaches and Alternatives
  • Dust: Open-Source Actors for Java
  • Redefining Java Object Equality

Trending

  • Why Database Migrations Take Months and How to Speed Them Up
  • Data Quality: A Novel Perspective for 2025
  • AI-Driven Root Cause Analysis in SRE: Enhancing Incident Resolution
  • A Simple, Convenience Package for the Azure Cosmos DB Go SDK
  1. DZone
  2. Coding
  3. Java
  4. Java Concurrency: Visibility and Synchronized

Java Concurrency: Visibility and Synchronized

In this post, gain insight into variable visibility between two threads and what happens when we change a variable that is shared.

By 
Emmanouil Gkatziouras user avatar
Emmanouil Gkatziouras
DZone Core CORE ·
Aug. 28, 24 · Code Snippet
Likes (6)
Comment
Save
Tweet
Share
8.4K Views

Join the DZone community and get the full member experience.

Join For Free

Previously, we examined the happens before guarantee in Java. This guarantee gives us confidence when we write multithreaded programs with regard to the re-ordering of statements that can happen. In this post, we shall focus on variable visibility between two threads and what happens when we change a variable that is shared.

Code Examination

Let’s examine the following code snippet:

Java
 
import java.util.Date;
 
public class UnSynchronizedCountDown {
    private int number = Integer.MAX_VALUE;
 
    public Thread countDownUntilAsync(final int threshold) {
        return new Thread(() -> {
            while (number>threshold) {
                number--;
                System.out.println("Decreased "+number +" at "+ new Date());
            }
        });
    }
 
    private void waitUntilThresholdReached(int threshold) {
        while (number>threshold) {
        }
    }
 
    public static void main(String[] args) {
        int threshold = 2125840327;
 
        UnSynchronizedCountDown unSynchronizedCountDown = new UnSynchronizedCountDown();
        unSynchronizedCountDown.countDownUntilAsync(threshold).start();
 
        unSynchronizedCountDown.waitUntilThresholdReached(threshold);
        System.out.println("Threshold reached at "+new Date());
    }
}


This is a bad piece of code: two threads operate on the same variable number without any synchronization. Now the code will likely run forever! Regardless of when the countDown thread reaches the goal, the main thread will not pick the new value which is below the threshold. This is because the changes made to the number variable have not been made visible to the main thread. So it’s not only about synchronizing and issuing thread-safe operations but also ensuring that the changes a thread has made are visible.

Visibility and Synchronized

Intrinsic locking in Java guarantees that one thread can see the changes of another thread. So when we use synchronized the changes of a thread become visible to the other thread that has stumbled on the synchronized block.

Let’s change our example and showcase this:

Java
 
package com.gkatzioura.concurrency.visibility;
 
 
public class SynchronizedCountDown {
    private int number = Integer.MAX_VALUE;
    private String message = "Nothing changed";
    private static final Object lock = new Object();
 
    private int getNumber() {
        synchronized (lock) {
            return number;
        }
    }
 
    public Thread countDownUntilAsync(final int threshold) {
        return new Thread(() -> {
            message = "Count down until "+threshold;
            while (number>threshold) {
                synchronized (lock) {
                    number--;
                    if(number<=threshold) {
                    }
                }
            }
        });
    }
 
    private void waitUntilThresholdReached(int threshold) {
        while (getNumber()>threshold) {
        }
    }
 
    public static void main(String[] args) {
        int threshold = 2147270516;
 
        SynchronizedCountDown synchronizedCountDown = new SynchronizedCountDown();
        synchronizedCountDown.countDownUntilAsync(threshold).start();
        System.out.println(synchronizedCountDown.message);
 
        synchronizedCountDown.waitUntilThresholdReached(threshold);
        System.out.println(synchronizedCountDown.message);
    }
}


Access to the number variable is protected by a lock. Also modifying the variable is synchronized using the same lock.

Eventually, the program will terminate as expected since we will reach the threshold. Every time we enter the synchronized block the changes made by the countdown thread will be visible to the main thread. This applies not only to the variables involved on a synchronized block but also to the variables that were visible to the countdown thread. Thus although the message variable was not inside any synchronized block at the end of the program its altered value got publicized, thus saw the right value printed.

Java (programming language) Lock (computer science) Data Types

Published at DZone with permission of Emmanouil Gkatziouras, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Recurrent Workflows With Cloud Native Dapr Jobs
  • Avoiding If-Else: Advanced Approaches and Alternatives
  • Dust: Open-Source Actors for Java
  • Redefining Java Object Equality

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: