0

I have an object which contains tons of class fields (primitives and custom objects). This object is accessed in a way that its methods are executed by one thread at a time (no synchronization on the methods or on the class itself).

I would like to know the following: Even if the object is used by one thread at a time, it's still shared and its internal state must be shared along all the threads in order to prevent inconsistent state. The object is stored/retrieved from a collection, and the collection is accessed with synchronized methods.

Does synchronization on the collection (actually a map) guarantee that my object's fields will be visible for all the other threads? Please note that the object's fields are not volatile/synchronized.

Follows some code describing three ways of storing/retrieving the objects from the map. Once retrieved they belong to one and only one thread. Once put inside the map again they can be reusde by another thread.

Code:

public class POJO {

    private int varA;

    private CustomObj varB;

    private String varC;

    private AnOtherObj varD;

    ...

    public void executeA(...) {

        ...
    }

    public void executeB(...) {

        ...
    }
}

I can access the map in which POJO must be stored through these following methods which do not belong to POJO class.

public void updatePOJO(POJO pojo) {
    //ReentrantLock
    locker.lock();
    map.put(pojo,Status.UPDATED);
    locker.unlock();    
}

public POJO getPOJO() {
    //ReentrantLock
    locker.lock();
    POJO returnValue = map.keySet().iterator().next();
    locker.unlock();
    return returnValue;
}

public void updatePOJO_2(POJO pojo) {

    synchronized(map){
        map.put(pojo,Status.UPDATED);
    }
}
public POJO getPOJO_2() {

    synchronized(map) {
        return map.keySet().iterator().next();
    }
}

public void updatePOJO_3(POJO pojo) {

    //Assuming map is a Collections.SynchronizedMap
    map.put(pojo,Status.UPDATED);
}
public POJO getPOJO_3() {

    //synchronization must occur since we ask objects through the iterator
    synchronized(map) {

        //Assuming map is a Collections.SynchronizedMap
        return map.keySet().iterator().next();
    }
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Francesco Rizzi
  • 631
  • 6
  • 24
  • 2
    I'd like to see code, but I think the answer is "probably" yes. Synchronization makes a *happens-before* relationship with **all actions** on a thread, including all reads and writes, and that's what you need for visibility. – markspace May 07 '20 at 19:28
  • Hi markspace, the code has been added, please check it out, thanks – Francesco Rizzi May 07 '20 at 19:39
  • Are you asking which of those will work? They all will, but you must use only one. To properly synchronize, two threads must synchronize on the same lock or monitor (monitor = `synchronized` keyword). If they don't, it doesn't work. – markspace May 07 '20 at 19:46
  • (You have a further problem that the `POJO` you return will not be thread safe if it is modified by two threads concurrently. I assume when you said you can guarantee single access that's what you were talking about. Correct?) – markspace May 07 '20 at 19:47
  • Single acess is granted, but the POJO's internal state altered by thread 1 must be visible by thread 2 when thread 2 can access the obiect (i.e. getPojo returns something). Yes, i was wondering if all those three ways are correct to share POJO data with all the other threads. So i think that I don't have to worry about any further volatile synchronization on the POJO itself. This is important because POJO class can be extended and I do not want that the developer should keep in mind synchronization logics. – Francesco Rizzi May 07 '20 at 19:52
  • Take in mind that the exclusive access logic is not present in the code i posted. – Francesco Rizzi May 07 '20 at 19:54
  • I think your code is correct. I'm still worried about this "exclusive access logic" but as long as you're sure it's working then it should be fine. – markspace May 07 '20 at 20:01
  • Yes, thank you very much. The logic behind the exclusive access is that POJOs objects are actually stored/retrieved from a POOL, so that they can be reused over time by one thread at a time. – Francesco Rizzi May 07 '20 at 20:24
  • Since this question appears to be entirely about the `synchronized` keyword, I think it should be closed as a duplicate (and note that locks are defined to have the same semantics as a monitor lock-unlock.) – markspace May 07 '20 at 21:19
  • It explained well the happens-before relationship – Francesco Rizzi May 08 '20 at 12:26

0 Answers0