OCPJP6
Raymond Tong wrote:For the first case, class ThreeStooges does not have method to modify the content of stooges.
It only has isStooge method which check if name is contained inside stooges (read only).
Since, it is a read only action, and no one else could change the content of stooges once initialized, it is fine for concurrent access.
Greg Bag wrote:What about code #2 and #3?
Interesting... So concurrent read only is mostly thread-safe.
Chan Ag wrote:
HolderObject is worse than Holder cause even the construction is not complete till the initialize method is called. Nothing stops you from calling the initialize on a HolderObject more than once thereby changing its state. You don't even require extra threads for that. That is not what immutable objects allow.
Chan Ag wrote:
Interesting... So concurrent read only is mostly thread-safe.
I don't think so, but I am not sure and I think it has many ifs and buts applicable
Steve
Greg Bag wrote:
Raymond Tong wrote:For the first case, class ThreeStooges does not have method to modify the content of stooges.
It only has isStooge method which check if name is contained inside stooges (read only).
Since, it is a read only action, and no one else could change the content of stooges once initialized, it is fine for concurrent access.
Interesting... So concurrent read only is mostly thread-safe. What about code #2 and #3?
Chan Ag wrote:
About the following -
Interesting... So concurrent read only is mostly thread-safe.
I don't think so, but I am not sure and I think it has many ifs and buts applicable and it's way too complicated than it sounds. So I will wait to hear what the experts have to say to that. :-)
The rules are in the Java Memory Model, we could summarize but it would be lacking completeness. The link defines what guarantees can be made and when, anything else is a possible race condition.Greg Bag wrote:Also, what are the rules to publishing something successfully? What should i follow?
The visibility guarantee is only guaranteed when there is a 'happens-before' relationship - when the set happens-before the get. The link defines when the happens-before relationship exists. It doesn't exist just at the end of a synchronized block, it needs the end of a synchronized block and the start of another on the same object. And happens-before isn't about simple timing, it is about re-ordering and when memory is guaranteed to be published. So even if the set occurs well before the get, since there is no happens-before relationship (no synchronization barrier) the get operation still may not see the set operation.Also another thing, let's say Thread A calls the setter method and sets value to 5. Since it's synchronized, there is no corruption and visiblity is there.
Steve
Steve Luke wrote: The rules are in the Java Memory Model, we could summarize but it would be lacking completeness. The link defines what guarantees can be made and when, anything else is a possible race condition.
Greg Bag wrote:1) What if final keyword was missing on the hashset? My assumption is that it is not properly published and other threads can see a mid-constructed object.
2) Lets say synchronized is missing on the containsPerson. Thread A calls addPerson(new Person("John")); 5 seconds later, Thread B calls containsPerson(new Person("John")), will it actually see the updated Person("John") object from thread A?
My assumption is no
3) My assumption is that writes only occur in the constructor. Since there are no writes other than the constructor, there will be no visibility issues if you call containsPerson. So in my opinion, synchronized can be omitted on the getter.
I think you covered most of them previously - remove the final keyword, make a setter method, make the containsPerson() method modify the set somehow. Note, the person you get in could be modified while you search, which could affect the outcome of the search but it wouldn't affect the safety of the set.4) What changes would make this class not properly published?
5) What if Person is mutable? If a thread updates a Person, will all other threads see the updated Person in the hashset?
Also overall in general the only thing that really confuses me is proper publication. What is the best way to publish a mutable class? Is the following class I wrote properly published? Thread-safe?
So this is a class that has both immutable and mutable fields. Host is immutable and guests are mutable.
My assumptions:
1) Both host and guests should be final for it to be properly published. Why?
2) getHost() does not need to be synchronized because it's created only once in the constructor and never changed. So no visibility problems.
Steve
Sresh Rangi wrote:In one of these example, there are mutations to the object after the final variable is set. I don't think they are guaranteed to be visible. Consider two examples:
Example 1:
Example 2:
In example 1, the set is mutated after the instance variable is set. We have actions:
a) Thread1: - mySet initialization
b) Thread1: - set add
c) Thread2: - set contains
The happens-before relationships are: hb(a, b) and hb(a, c). This allows the orderings a -> b -> c and a -> c -> b.
In example 2, the set is mutated before the instance variable is set. We have actions:
a) Thread1: a - set add
b) Thread1: b - mySet initialization
c) Thread2: c - set contains
The happens-before relationships are: hb(a, b) and hb(b, c). This only allows a -> b -> c.
So reading a final variable only guarantees visibility of actions that happen before it's set.
Mike Simmons wrote:The final is also important in the very first example, with the HashSet:
Without final here, the HashSet would not be considered safely published upon completion of the ThreeStooges constructor, and there would be no guarantee that all the add() calls had completed in the constructing thread, before some other thread calls isStooge(). Without a final stooges field, ThreeStooges cannot be considered an immutable class - even if it has no accessors and the class itself is final. The field needs to be final too.
I'm slightly confused here and I'm hoping you'd want to correct me so I get this answer once and for all ( cause it has kind of confused me every time I have tried to understand it ). So are you (both? ) saying that the three adds in the Greg's first example are not guaranteed to show at the time the ThreeStooges constructor returns? I mean are you saying that at the time the constructor returns, it is guaranteed that stooges will not be null but the three adds have completed is not guaranteed?
- JSR 133The usage model for final fields is a simple one. Set the final fields for an object in that object’s
constructor. Do not write a reference to the object being constructed in a place where another
thread can see it before the object’s constructor is finished. If this is followed, then when the
object is seen by another thread, that thread will always see the correctly constructed version of
that object’s final fields. It will also see versions of any object or array referenced by those final
fields that are at least as up-to-date as the final fields are.
"Eagles may soar but weasels don't get sucked into jet engines" SCJP 1.6, SCWCD 1.4, SCJD 1.5,SCBCD 5
Sresh Rangi wrote:In one of these example, there are mutations to the object after the final variable is set. I don't think they are guaranteed to be visible. Consider two examples:
Example 1:
Example 2:
In example 1, the set is mutated after the instance variable is set. We have actions:
a) Thread1: - mySet initialization
b) Thread1: - set add
c) Thread2: - set contains
The happens-before relationships are: hb(a, b) and hb(a, c). This allows the orderings a -> b -> c and a -> c -> b.
In example 2, the set is mutated before the instance variable is set. We have actions:
a) Thread1: a - set add
b) Thread1: b - mySet initialization
c) Thread2: c - set contains
The happens-before relationships are: hb(a, b) and hb(b, c). This only allows a -> b -> c.
So reading a final variable only guarantees visibility of actions that happen before it's set.
- JSR133It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.
"Eagles may soar but weasels don't get sucked into jet engines" SCJP 1.6, SCWCD 1.4, SCJD 1.5,SCBCD 5
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime. |