开发者

Do I need to synchronize access to immutable types in Java?

Let's say I have this class:

class Zoo
{
    protected String bearName;
    protected Double trainerSalary;
    protected Integer monkeyCount;
}

Can one thread write to these fields, and another one read them, without requiring synchronized access to the Zoo object?

Note: thes开发者_JAVA技巧e values can be treated separate from one another, so it doesn't matter that the trainerSalary is changed while the monkeyCount is read.

EDIT:

Just to clarify, the fields are mutable; only their referenced objects are immutable.


Technically you need to make them final, volatile or read and write them using synchronzied to guarantee that the reader will read the most up-to-date value. As you have it right now, if one thread writes in a value, there's no guarantee that another thread will read the same value. This is because the the reading thread may see a cached valued. This is more likely with multi-core CPUs and various levels of cache.

A great book on this is Java Concurrency in Practice.


Accesses and updates to the memory cells corresponding to fields of any type except long or double are guaranteed to be atomic (see Concurrent Programming In Java). That's why one might expect that you don't need to synchronize read access to your fields. However, the Java memory model allows threads to cache previously read values in case you access them repeatedly so you should mark the fields as volatile to ensure that each thread sees the most recent values.

If you are sure that nobody will change the values of the fields, make them final. In that case, no volatile field is necessary.

Things are different if the values of the fields depend on each other. In that case, I'd recommend to use synchronized setters that ensure that the invariant of your class is not violated.


As you've stated the class it's possible for another class in the same package to change these values. This class isn't immutable.

Now if you did something like

class Zoo
{
    protected final String bearName;
    protected final Double trainerSalary;
    protected final Integer monkeyCount;
}

Then the class would be immutable. If the logic of your program treats this class as immutable, then why not make it actually immutable?

Also, if multiple threads were checking and updating the same value then you could have issue. Say multiple threads were checking and updating monkeyCount, then there is a good chance monkeyCount would end up incorrect because there is nothing that is forcing these check and updates to occur atomically.


My 2 cents, from "The Java Programming Language", 4 ed., 14.10.2 : "There is a common misconception that shared access to immutable objects does not require any synchronization because the state of the object never changes. This is a misconception in general because it relies on the assumption that a thread will be guaranteed to see the initialized state of the immutable object, and that need not be the case. The problem is that, while the shared object is immutable, the reference used to access the shared object is itself shared and often mutable - consequently, a correctly synchronized program must synchronize access to that shared reference, but often programs do not do this, because programmers do not recognize the need to do it. For example, suppose one thread creates a String object and stores a reference to it in a static field. A second thread then uses that reference to access the string. There is no guarantee, based on what we've discussed so far, that the values written by the first thread when constructing the string will be seen by the second thread when it accesses the string."


If those variables are indeed independent, then no, you do not need synchronization. However, as you note, if you had

protected Integer monkeysLeft;
protected Integer monkeysEatenByBears;

where the two variables are logically connected, you would want synchronized access to the pair of them.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜