Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Visibility of shared members  RSS feed

 
Peter Muster
Ranch Hand
Posts: 74
5
Eclipse IDE Python Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I have two questions regarding visibility of members of an object accessed by multiple threads.

Let's say I have a class Z providing a singleton object X through a static method getInstance().

I'd lazily load this singleton upon the first call of getInstance().

To make sure the singleton is instantiated only once I synchronize on the static class instance.



During initialization I set some class members that are not modified afterwards. Some of these are arrays but the array content is set during initialization and not written to afterwards, only read from.

Question 1.) Is it guaranteed that each member's current value is visible to any thread calling getInstance() after the first invocation? Another way to achieve this would probably be to declare each of these members final and set them in the constructor but this would put a lot of work in the constructor that doesn't really belong there and that I outsourced to multiple init... methods which are called from init().

Question 2.) X has an Integer A that I want to atomically increment / decrement. As an Integer is immutable and updating the value would create a new Integer object referenced by A I can't really synchronize on it. I have an object B though that exists for the entire life cycle in which A is incremented / decremented, so my question is: If I consistently synchronize on B before reading from or writing to A, is it guaranteed that all threads will see the most up to date value of A?

I have run a lot of tests, accessing the instance with up to several hundred threads at once and the results look fine, but I'm still in doubt about the two aspects described above and you never know when a very rare concurrency bug will hit you...

Looking very much forward to replies. :-)
 
Campbell Ritchie
Sheriff
Posts: 53720
127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That looks very iffy code. You might be able to synchronise but that is no way to ensure a singleton. Should you want a singleton (and that is doubtlful) you create it as an instanceIf you make the Foo class serialisable you would need a readResolve method.
 
Campbell Ritchie
Sheriff
Posts: 53720
127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christian Pflug wrote:. . . a singleton object X . . . each member's current value is visible to any thread calling getInstance() after the first invocation? . . .
Fields are usually not visible at all, since they ought to be private. If it is a singleton, then you will have one instance and one instance only; all using classes will see the same instance. Updates in one thread will be reflected in other threads but you cannot make any guarantees about happens‑before.
. . . X has an Integer A that I want to atomically increment / decrement. As an Integer is immutable . . .
That is a contradiction in terms. As you say yourself you cannot increment an Integer object. You cannot make something like…atomic. You can synchronise it, or I think i++ might be atomic if i is an int (not sure however), or you can use an Atomic version of Integer.
 
Henry Wong
author
Sheriff
Posts: 22825
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christian Pflug wrote:
Question 1.) Is it guaranteed that each member's current value is visible to any thread calling getInstance() after the first invocation? Another way to achieve this would probably be to declare each of these members final and set them in the constructor but this would put a lot of work in the constructor that doesn't really belong there and that I outsourced to multiple init... methods which are called from init().


Yeah, it should be fine. The threading optimizations that may create cache copies (such as data in registers) are guaranteed to be flushed upon crossing a synchronized boundary. Also, these optimizations don't keep these copies very long (as registers are scarce) ; they will very likely be flushed upon the return from the method call, meaning for your example, flushed even before reaching the synchronized boundary.

Henry
 
Peter Muster
Ranch Hand
Posts: 74
5
Eclipse IDE Python Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
At first thank you all for your prompt replies. :-)

Campbell Ritchie wrote:That looks very iffy code. You might be able to synchronise but that is no way to ensure a singleton. Should you want a singleton (and that is doubtlful) you create it as an instanceIf you make the Foo class serialisable you would need a readResolve method.

My code is not so much different from yours. I've only used a simplified representation in this thread. My class Z (or Foo) does have a private constructor. It has a private static instance which I named X in my example (and you named yours INSTANCE). The difference is that I create a new instance when it is first requested through getInstance() while you assign it a new instance in the member declaration. As a consequence I cannot declare it final but it's still private and not modified within the class so another class shouldn't be able to compromise that.

Basically your singleton instance is created when the class is loaded the first time, mine is created when a thread requests the singleton the first time. I guess there are pros and cons for both versions but I would stick to my implementation unless there are some serious arguments against it (like it could cause a bug in a concurrent environment).

Campbell Ritchie wrote:
Christian Pflug wrote:. . . a singleton object X . . . each member's current value is visible to any thread calling getInstance() after the first invocation? . . .
Fields are usually not visible at all, since they ought to be private. If it is a singleton, then you will have one instance and one instance only; all using classes will see the same instance. Updates in one thread will be reflected in other threads but you cannot make any guarantees about happens‑before.
. . . X has an Integer A that I want to atomically increment / decrement. As an Integer is immutable . . .
That is a contradiction in terms. As you say yourself you cannot increment an Integer object. You cannot make something like…atomic. You can synchronise it, or I think i++ might be atomic if i is an int (not sure however), or you can use an Atomic version of Integer.


Okay I think I didn't describe the situation accurately enough. My instance X which is accessed by multiple threads concurrently has some private members which are accessed in methods that are public and that threads can invoke on the singleton instance concurrently. One such method for example will take the value of a member into consideration to perform a calculation and return the result to the caller. The members themselves are never exposed to the threads.

Technically I don't have an Integer A, I have a reference to an Integer that I named A. Let me get into details a bit to avoid confusion. My instance X takes care of a number of objects stored in a collection that can be modified. If a thread attempts to modify an object, a counter for that respective object is incremented. Once the thread has finished modifying the object the counter is decremented again. The instance X provides a method which removes an object from the collection and replaces it with a new one. This should only be possible though if no other thread is currently waiting to modify the object that is going to be replaced. To keep track of the number of threads waiting on an object, I increment an Integer reference stored in a ConcurrentHashMap. In my example I simplified that to A. Each object has a lock representation so basically I perform something like that:


With these additional information let me rephrase my question:

To my understanding each thread keeps its own copy of the singleton object in a cache. Synchronization ensures that only one thread accesses an object at the time and that modifications on the object gets published to all other threads. In this case I do not synchronize on the object that I modify. My member waitCount is a ConcurrentHashMap and thus thread-safe by definition, by synchronizing on the lock object for the respective entry in the map atomicity is guaranteed. My multi step operation of "getting the value from the map", "incrementing the value" and "writing it back to the map" is guaranteed to be atomic in regard to other threads invoking it if the value is only ever modified through synchronization on the same object, but... Does synchronizing on "obj" as I do in my code guarantees that all threads will receive the latest value for "waitCount.get(obj)" if they synchronize on "obj" as well when reading it?

More generally phrased: When synchronizing a block of code, are all modifications made on objects shared between multiple threads within that block of code published to other threads or only the object that I synchronize on?

Henry Wong wrote:
Christian Pflug wrote:
Question 1.) Is it guaranteed that each member's current value is visible to any thread calling getInstance() after the first invocation? Another way to achieve this would probably be to declare each of these members final and set them in the constructor but this would put a lot of work in the constructor that doesn't really belong there and that I outsourced to multiple init... methods which are called from init().


Yeah, it should be fine. The threading optimizations that may create cache copies (such as data in registers) are guaranteed to be flushed upon crossing a synchronized boundary. Also, these optimizations don't keep these copies very long (as registers are scarce) ; they will very likely be flushed upon the return from the method call, meaning for your example, flushed even before reaching the synchronized boundary.

Henry

This sounds like it confirms my assumption regarding the second question as well, right? Synchronizing on an object will always publish all changes made to any shared objects inside the synchronization block...
 
Henry Wong
author
Sheriff
Posts: 22825
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christian Pflug wrote:
To my understanding each thread keeps its own copy of the singleton object in a cache. Synchronization ensures that only one thread accesses an object at the time and that modifications on the object gets published to all other threads. In this case I do not synchronize on the object that I modify.


I would be really careful with such a statement. There is no such a thing as an object cache related to threads. The "cache" being mentioned here are simply related to the memory model and optimizations around the use of register variables.

These types of "caching" are simply related to memory cache lines, which are often measured in bytes (and not objects). Furthermore, they are affected by if the thread blocks, context switches, or even if an interrupt happens. In fact, it may be hard to write an example to prove that it is even happening.

Henry
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christian Pflug wrote:Basically your singleton instance is created when the class is loaded the first time, mine is created when a thread requests the singleton the first time. I guess there are pros and cons for both versions but I would stick to my implementation unless there are some serious arguments against it (like it could cause a bug in a concurrent environment).


I would definitely not use your lazy loading version. It is more complicated than the basic static instance version so is more likely to either not be thread-safe (because you make a mistake in the implementation), or because someone else comes along later and makes a change that makes it not thread safe.

The static version can easily be made lazy-loading if that is definitely what you need. Either:

1) The only static member of the class is getInstance(), therefore the first access of the class and the first attempt to get the instance are always going to be the same.

2) The class has other static methods or fields that can be accessed without creating the instance, in which case you can do the following:



Christian Pflug wrote:This sounds like it confirms my assumption regarding the second question as well, right? Synchronizing on an object will always publish all changes made to any shared objects inside the synchronization block...


Yes, synchronizing on any lock will guarantee a happens-before relationship with subsequent locks of the same monitor. It doesn't matter what lock is used as long as both threads are synchronizing on the same thing.

From the Java memory model (section 17.4 of the Java Language Specification).


An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).


Followed by:

If an action x synchronizes-with a following action y, then we also have hb(x, y)


where hb(x,y) means x happens-before y.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!