Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8423097
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 10, 20262026-06-10T03:38:16+00:00 2026-06-10T03:38:16+00:00

I am reading the book Java Concurrency in Practice session 4.3.5 @ThreadSafe public class

  • 0

I am reading the book Java Concurrency in Practice session 4.3.5

  @ThreadSafe
  public class SafePoint{

       @GuardedBy("this") private int x,y;

       private SafePoint (int [] a) { this (a[0], a[1]); }

       public SafePoint(SafePoint p) { this (p.get()); }

       public SafePoint(int x, int y){
            this.x = x;
            this.y = y;
       }

       public synchronized int[] get(){
            return new int[] {x,y};
       }

       public synchronized void set(int x, int y){
            this.x = x;
            this.y = y;
       }

  }

I am not clear where It says

The private constructor exists to avoid the race condition that would occur if the copy constructor were implemented as this (p.x, p.y); this is an example of the private constructor capture idiom (Bloch and Gafter, 2005).

I understand that it provides a getter to retrieve both x and y at once in a array instead of a separate getter for each, so the caller will see consistent value, but why private constructor ? what’s the trick here

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-10T03:38:17+00:00Added an answer on June 10, 2026 at 3:38 am

    There are already a bunch of answers here, but I would really like to dive into some details (as much as my knowledge let’s me). I will strongly advise you to run each sample that is present here in the answer to see for yourself how things are happening and why.

    To understand the solution, you need to understand the problem first.

    Suppose that the SafePoint class actually looks like this:

    class SafePoint {
        private int x;
        private int y;
    
        public SafePoint(int x, int y){
            this.x = x;
            this.y = y;
        }
    
        public SafePoint(SafePoint safePoint){
            this(safePoint.x, safePoint.y);
        }
    
        public synchronized int[] getXY(){
            return new int[]{x,y};
        }
    
        public synchronized void setXY(int x, int y){
            this.x = x;
            //Simulate some resource intensive work that starts EXACTLY at this point, causing a small delay
            try {
                Thread.sleep(10 * 100);
            } catch (InterruptedException e) {
             e.printStackTrace();
            }
            this.y = y;
        }
    
        public String toString(){
          return Objects.toStringHelper(this.getClass()).add("X", x).add("Y", y).toString();
        }
    }
    

    What variables create the state of this object? Just two of them : x,y. Are they protected by some synchronization mechanism? Well they are by the intrinsic lock, through the synchronized keyword – at least in the setters and getters. Are they ‘touched’ anywhere else? Of course here:

    public SafePoint(SafePoint safePoint){
        this(safePoint.x, safePoint.y);
    } 
    

    What you are doing here is reading from your object. For a class to be Thread safe, you have to coordinate read/write access to it, or synchronize on the same lock. But there is no such thing happening here. The setXY method is indeed synchronized, but the clone constructor is not, thus calling these two can be done in a non thread-safe way. Can we brake this class?

    Let’s try this out:

    public class SafePointMain {
    public static void main(String[] args) throws Exception {
        final SafePoint originalSafePoint = new SafePoint(1,1);
    
        //One Thread is trying to change this SafePoint
        new Thread(new Runnable() {
            @Override
            public void run() {
                originalSafePoint.setXY(2, 2);
                System.out.println("Original : " + originalSafePoint.toString());
            }
        }).start();
    
        //The other Thread is trying to create a copy. The copy, depending on the JVM, MUST be either (1,1) or (2,2)
        //depending on which Thread starts first, but it can not be (1,2) or (2,1) for example.
        new Thread(new Runnable() {
            @Override
            public void run() {
                SafePoint copySafePoint = new SafePoint(originalSafePoint);
                System.out.println("Copy : " + copySafePoint.toString());
            }
        }).start();
    }
    }
    

    The output is easily this one:

     Copy : SafePoint{X=2, Y=1}
     Original : SafePoint{X=2, Y=2} 
    

    This is logic, because one Thread updates=writes to our object and the other is reading from it. They do not synchronize on some common lock, thus the output.

    Solution?

    • synchronized constructor so that the read will synchronize on the same lock, but Constructors in Java can not use the synchronized keyword – which is logic of course.

    • may be use a different lock, like Reentrant lock (if the synchronized keyword can not be used). But it will also not work, because the first statement inside a constructor must be a call to this/super. If we implement a different lock then the first line would have to be something like this:

      lock.lock() //where lock is ReentrantLock, the compiler is not going to allow this for the reason stated above.

    • what if we make the constructor a method? Of course this will work!

    See this code for example

    /*
     * this is a refactored method, instead of a constructor
     */
    public SafePoint cloneSafePoint(SafePoint originalSafePoint){
         int [] xy = originalSafePoint.getXY();
         return new SafePoint(xy[0], xy[1]);    
    }
    

    And the call would look like this:

     public void run() {
          SafePoint copySafePoint = originalSafePoint.cloneSafePoint(originalSafePoint);
          //SafePoint copySafePoint = new SafePoint(originalSafePoint);
          System.out.println("Copy : " + copySafePoint.toString());
     }
    

    This time the code runs as expected, because the read and the write are synchronized on the same lock, but we have dropped the constructor. What if this were not allowed?

    We need to find a way to read and write to SafePoint synchronized on the same lock.

    Ideally we would want something like this:

     public SafePoint(SafePoint safePoint){
         int [] xy = safePoint.getXY();
         this(xy[0], xy[1]);
     }
    

    But the compiler does not allow this.

    We can read safely by invoking the *getXY method, so we need a way to use that, but we do not have a constructor that takes such an argument thus – create one.

    private SafePoint(int [] xy){
        this(xy[0], xy[1]);
    }
    

    And then, the actual invokation:

    public  SafePoint (SafePoint safePoint){
        this(safePoint.getXY());
    }
    

    Notice that the constructor is private, this is because we do not want to expose yet another public constructor and think again about the invariants of the class, thus we make it private – and only we can invoke it.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am reading this book called Java Concurrency in Practice and the author gives
So I am reading this book titled Java Concurrency in Practice and I am
I'm reading the Book Java Concurrency in Practice . In chapter 15, they are
I am reading the book Java Concurrency in Practice . In Chapter 4.2 -
I am reading the book Java Concurrency in Practice and getting a little bit
I am reading Java Concurrency in Practice and kind of confused with the thread
I've been reading up on Doug Lea's 'Concurrency Programming in Java' book. As you
While i was reading java book, i came across Every class extends class Object
I'm reading Sybex Complete Java 2 Certification Study Guide April 2005 (ISBN0782144195). This book
I am reading the 7th chapter of Java Concurrency in Practice. In a section

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.