Should I access (not change) an object from multiple threads? - java

My situation is that I have two threads. The 1st thread produces a number of objects which the 2nd thread does not have access to until all of them are created. After that the 2nd thread reads fields in those objects but does so concurrently with the 1st. At this point no thread is changing the values of the fields of the objects.
The objects are not synchronized. Should I synchronize them or not?

What I would recommend is to use an AtomicReference<Collection<SomeObject>>. The first thread would produce the collection of objects and do a reference.put(collection). The 2nd thread would see the objects (reference.get()) after they have been set on the AtomicReference only. Here are the javadocs for AtomicReference. You could also set your objects as an array or any type of collection such as List.
If is important to realize that after your set the collection (or array) on the AtomicReference you cannot make any changes to the collection. You can't add additional items, clear it, etc.. If you want true concurrent access to a collection of objects then you should look into ConcurrentHashMap and friends.
Should I synchronize them or not?
If the objects are not going to be mutated at all after they are put in your collection then you do not need to make them synchronized.

There's nothing wrong with reading data from multiple threads at the same time. Issues arise when you attempt to modify that data. So long as the objects are fully initialized and the values are such that the second thread receives the actual value (no issues with caching etc), there no problem with reading data from multiple threads concurrently.

Related

Why are we here, specifically, saying that ArrayList is not thread safe?

Description: If we use same object reference among multiple threads, no object is thread safe. Similarly, if any collection reference is shared among multiple threads then that collection is not thread-safe since other threads can access it. So, Why are we here specifically saying that ArrayList is not thread-safe? What about the other Collections?
You misunderstand the meaning of "thread-safe."
When we say "class X is thread-safe," We are not saying that you don't have to worry about the thread-safety of a program that uses it. If you build a program using nothing but thread-safe objects, that does not guarantee that your program will be thread-safe.
So what does it guarantee?
Suppose you have a List. Suppose that two threads, A and B, each write different values to the same index in the list, suppose that some thread C reads from that index, and suppose that none of those three threads uses any synchronization.
If the list is "thread-safe," then you can be assured that thread C will get one of three possible values:
The value that thread A wrote,
The value that thread B wrote,
The value that was stored at that index before either thread A or thread B wrote.
If the list is not thread-safe, then any of those same three things could happen, but also, other things could happen:
Thread C could get a value that was never in the list,
The list could behave in broken ways in the future for thread C even if no other thread continues to use it,
The program could crash,
etc. (I don't know how many other strange things could happen.)
When we say that a class is "thread-safe" we are saying that it will always behave in predictable, reasonable ways, even when its methods are concurrently called by multiple threads.
If you write a program that uses a "thread-safe" list, and if it depends on thread C reading one particular value of the three possibilities that I listed above, then your program has a thread-safety problem, even though the list itself does not.
I haven't checked but I think that all standard Collection implementations state if they are thread-safe or not. So you know if you can share that collection among different threads without synchronization.
CopyOnWriteArrayList for example is a thread-safe List implementation.
ArrayList is unsynchronized in implementation. When an object is unsynchronized it means that is is not locked while being modified structurally. A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.
What you are referring to is an array which the elements are being added to or being deleted from and can be modified this differs from it having its value being set.
Reference is in regards with the pointer of the start of the array but how many elements are there is in question and having an unsynchronized object being modified in the sense of elements while the elements are being iterated over by another thread the integrity of the elements in the list is hard to guarantee. I hope I was able to convey the message plainly.
Look for more details here in Oracle: Array List and ConcurrentModificationException
ArrayList:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method.
ConcurrentModificationException:
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification.

What happens if an object is modified outside of the concurrent map in java?

What happens if an object is modified outside of the concurrent map in java?
Say, I have a concurrent hash map and in one thread I retrieve a value from that map and modify its state. Will the other threads see the modification without an additional synchronization?
The key concept in the Java Memory Model is the happens before relation. You can only rely on things happening between threads if there is a happens before relationship between the two of them.
In the case of ConcurrentHashMap, there is a happens-before relationship between a put and a subsequent get of the value for the same key: updating the value and putting it into the map happens before getting the value and reading its state. Because of that happens before relationship, the update happens before the reading of the state, so you will see the updated state.
So, if you update the state of an object, and then put it into the map, if you subsequently get it from the map, you are guaranteed to see that updated state (until such time as you put again).
But, if you have a reference to that object outside the context of a ConcurrentHashMap, there is no automatic happens-before relationship. You have to create that relationship for yourself.
One way of doing this is with synchronization (as in using synchronized, on the same object in all threads); other ways include:
writing and reading a volatile variable
using a Lock
putting the object into the map again, and then getting from the map before you start using it in the other thread.
Short answer is no.
A concurrent map will only synchronize the access to the map. That is, if one thread writes the map, all other threads can see that without additional synchronization.
If you retrieve an object from the map and modify it without synchronization, and if another thread retrieves the same object to read it, then you have a race without explicit synchronization between those threads.

Passing objects between threads

I have worker threads that generate objects and push them into a thread-safe Set. A processing thread periodically reads the Set and processes the elements.
While the object references themselves will be successfully retrieved from the set, the objects' variables are not thread-safe if accessed from the processing thread. Is there some pattern to do this, apart from making all the objects' internals volatile etc.? The objects may become more complex in the future, containing nested objects etc.
Assuming that no object will be externally modified by once placed into the Set, is there some way to "happens-before" whatever is currently in the Set before I begin processing it? The processing thread is already running and will not be created only after the Set has been populated.
The objects themselves are just data containers and have no inherent thread-safety. I can't make all the fields final since they may be modified multiple times before being placed into the Set.
If you have a thread safe set, this will establish happens before writes so you don't have to worry about whether the object is thread safe or not. This assumes that your producer doesn't alter or read the object after putting it in the collection.
If you make the objects immutable, this will make the relationship clearer, however I am assuming that once you pass the object to the shared storage, the writing thread no long alters the object and only the consuming thread reads or alters the object.
BTW I would pass the tasks via a queue using an ExecutorService as it is more efficient and written for you.
Volatile isn't quite the magic bullet in this case. Look at the possibility of switching to immutable objects for those passed between threads. Also, a threadsafe data structure that is queue based will give you better performance than most set implementations.

Java Concurrent Collections and visiblity

I'm getting a little unsure about what to expect from Concurrent Collections (e.g. ConcurrentMap) regarding visibility of the data in the collection.
A: Thread1 puts a complex object and Thread2 gets it. Will all attributes be visible in Thread2?
B: Thread1 puts a complex object and later changes some attributes. Then Thread2 gets it, will all changes be visible in Thread2?
I guess B is false, and if so I should synchronize every access on the complex object?
Pushing to a concurrent collection is defined as publishing it. See "Memory Consistency Properties" in the Package description.
This means if you just change a stored object, you do not get automatically a happens before relationship. You would need to make those changes synchronied/volatile or using a concurrent primitive itself.
A: If the object is immutable or if the object is mutable but all the properties are set before the object is added to the collection then yes, they will be all visible.
B: If no synchronisation mechanisms are in place then it is not guaranteed, it depends when the thread 2 accesses the object.
If you need this sort of behaviour guaranteed (i.e. the reading thread to be guaranteed to see all the modifications made by the mutator thread in a transactional-like manner) I suggest you set up a semaphoring mechanism. Even better, it would be simpler if you use immutable objects.

Can Java LinkedList be read in multiple-threads safely?

I would like multiple threads to iterate through the elements in a LinkedList. I do not need to write into the LinkedList. Is it safe to do so? Or do I need a synchronized list to make it work?
Thank you!
They can do this safely, PROVIDED THAT:
they synchronize with (all of) the threads that have written the list BEFORE they start the iterations, and
no threads modify the list during the iterations.
The first point is necessary, because unless there is proper synchronization before you start, there is a possibility that one of the "writing" threads has unflushed changes for the list data structures in local cache memory or registers, or one of the reading threads has stale list state in its cache or registers.
(This is one of those cases where a solid understanding of the Java memory model is needed to know whether the scenario is truly thread-safe.)
Or do I need a synchronized list to make it work
You don't necessarily need to go that far. All you need to do is to ensure that there is a "happens-before" relationship at the appropriate point, and there are a variety of ways to achieve that. For instance, if the list is created and written by the writer thread, and the writer then passes the list to the reader thread objects before calling start() on them.
From the Java documentation:
Note that this implementation is not synchronized. If multiple threads access a linked list concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.
In other words, if you are truly just iterating through then you're alright, just be careful.

Categories

Resources