Reputation: 1935
I'm currently learning about threads in java, and from what I've read, implementing them isn't the problem so much as making your code thread safe. Which brings me to my question: should I be using immutable objects whenever possible to ensure that I prevent concurrency bugs?
I've read differing opinions about when to use mutable objects, including:
If immutable objects are good, why do people keep creating mutable objects? (Programmers.SE)
for large and/or complex objects, creating a new copy of the object for every single change can be very costly and/or tedious. And for objects with a distinct identity, changing an existing objects is much more simple and intuitive than creating a new, modified copy of it.
Immutable Objects (Java Tutorials)
The impact of object creation is often overestimated, and can be offset by some of the efficiencies associated with immutable objects. These include decreased overhead due to garbage collection, and the elimination of code needed to protect mutable objects from corruption.
So, is there a best practice when implementing threads? Should I always try to use immutable objects when possible?
Upvotes: 4
Views: 724
Reputation: 2043
Yes, immutable objects are often your friend when multi-threading.
There are a few big pluses:
Threadsafe. If you can't change it's state, then there's no way that two threads can update it at the same time or see separate versions of it.
No locking. Because nothing changes, there's no need to use the synchronized
keyword. This gives you performance bonuses and simplicity.
Can be singleton. Since the object is thread-safe, there's no need to give separate threads their own version of it. You can pass it around to several threads knowing that the state won't change, preventing you from having to possibly spend more memory creating copies.
Upvotes: 1
Reputation: 8792
The problem with threaded access to an object is always one of changing the object safely; reading an object's state is inherently safe if you can guarantee that the state is not being changed at the same time. (Obviously my answer assumes you are changing objects in threaded code.)
Immutable objects simply mask this complexity - I now have to guarantee that the object I hold a reference to is not stale. In addition, I now have to determine where the most current version of that object is if the version I have is indeed stale.
Upvotes: 0
Reputation: 77177
Using truly immutable objects (no fields that contain references to mutable classes) is thread-safe, and it's a good habit to employ them when it's practical, but whether immutability is feasible depends on the specifics of the situation; some toolkits, for example, require setter or field injection and thus can't be used with immutable objects. Immutability is typically the most practical with the Value Object pattern, where the object doesn't have any especially complex behavior and basically encapsulates a clearly-describable value (String
, the primitive wrappers, Guava's Immutable*
collections).
Generally, I try to make objects with simple fields immutable whenever practical, and I find it helpful to start from the default that immutable objects are safest and only use mutators if there's a particular reason why they're needed.
Similarly, if you're going to rely on the immutability of a class for something like thread safety, you should usually declare the class final
to avoid all manner of headaches. I don't go so far as to insist that all classes must be either abstract
or final
, but final
instantiable classes are a good default.
Upvotes: 3
Reputation: 1498
I think it really depends on the context where you will be using them. Is it an object that will be accessed in multiple threads constantly? What are the hardware constraints on the system?
It's not so much about whether the objects are immutable or mutable, it's more about how they will be accessed. Even an immutable object can cause thread safety issues if it's being copied at the same time that the copy is being accessed...
You should probably look into ACID: http://en.wikipedia.org/wiki/ACID
Also Java has solid and easy to implement methods for synchronizing code so that mutable objects can be accessed safely from multiple threads. For a system that needs to be highly performant in terms of memory consumption this is likely the way to go. But again it's a trade off based on your constraints - what's more important memory or speed?
Upvotes: 0