In Java Concurrency In Practice, the author stated that
Immutable objects can be published through any mechanism
Immutable objects can be used safely by any thread without additional synchronization, even when synchronization is not used to publish them.
Does it mean that the following idioms are safe to publish immutable objects?
public static List<ImmutableObject> list = new ArrayList<ImmutableObject>();
// thread A invokes this method first
public static void methodA () {
list.add(new ImmutableObject());
}
// thread B invokes this method later
public static ImmutableObject methodB () {
return list.get(0);
}
Would there be any data race?
(which means thread B may not be able to see the Immutable Object in the list added by thread A)
Thank you very much.
More, the author said that the following code is safe if Resource is immutable.
#NotThreadSafe
public class UnsafeLazyInitialization {
private static Resource resource;
public static Resource getInstance() {
if (resource == null)
resource = new Resource(); // unsafe publication
return resource;
}
}
Section16.3
The guarantee of initialization safety allows properly constructed immutable objects to be safely shared across threads without synchronization, regardless of how they are published even if published using a data race. (This means that unsafeLazyInitialization is actually safe if Resource is immutable.)
For the 2nd part of this question, it is discussed in detail in another question (click here)
Yes, you are correct, there is a data race.
Only the ImmutableObject is immutable and can be shared safely between threads, your List, however, does not have these same guarantees, so there is a data race between adding the ImmutableObject and retrieving it.
In JCIP, the authors meant immutable objects are safe to publish in the sense that you don't have to worry about doing things like making defensive copies.
As to:
Immutable objects can be used safely by any thread without additional
synchronization, even when synchronization is not used to publish
them.
This statement means that given 2 threads with an immutable object A that they both acquired through any means, they can both use object A without worrying about thread-safety issues.
Your List<ImmutableObject> list container object is not immutable. Hence, add and get method on it will not be threadsafe. These methods need to be synchronized for concurrent access from multiple threads.
Your question suggests that you are anticipating section 5.3 - blocking queues and the producer consumer pattern. Here is something similar using a blocking queue:
public class Blocking
{
private BlockingQueue<ImmutableObject> queue = new ArrayBlockingQueue<ImmutableObject>(10);
public void methodA() {
queue.add(new ImmutableObject());
}
public ImmutableObject methodB() throws InterruptedException
{
return queue.take();
}
static class ImmutableObject
{
}
}
The blocking queue is highly mutable - but is designed to be thread safe so you can use it without extra synchronization. As long as the objects that you are passing are immutable the entire design is thread safe.
In the example above, methodB uses "take" which will block until methodA is called to put something in the queue. Or until the thread is interrupted at which point it would exit via an InteruptedException
Yes there is definite chance of data race. Here is a situation:
Although Thread A is inside methodA and then Thread B would be executing methodB, there is no guarantee that methodA has returned before methodB. If, unfortunately, methodB has already returned while methodA is yet to return, there would be high chance to get IndexOutOfBoundsException:
// thread A invokes this method first
public static void methodA () {
//assume control is taking time at this point, while thread B already returned!!!
list.add(new ImmutableObject());
}
// thread B invokes this method later
public static ImmutableObject methodB () {
return list.get(0);
}
Related
While working on a Producer Consumer problem I stumbled upon a scenario wherein I can synchronize on the field "sharedLinkedList" or on the entire object "this" of class "SharedObject".
"sharedLinkedList" is the field the Producer and Consumer threads are going to work on.
Please find a snippet of the class with the Produce method:-
public class SharedObject {
LinkedList<Integer> sharedLinkedList = new LinkedList<Integer>();
int capacity = 5;
public void produce() {
while (true) {
synchronized (sharedLinkedList) {// Alternately synchronized(this)
try {
while(sharedLinkedList.size() == capacity){
sharedLinkedList.wait();//Alternately this.wait()
}
} catch (InterruptedException e) {
e.printStackTrace();
}
sharedLinkedList.add(123);
sharedLinkedList.notify();//Alternately this.notify
}
}
}
}
Both the approaches work.
1. Synchronizing on the field "sharedLinkedList"
2. Synchronizing on the entire object (put as a comment in the code snippet).
Which is a better approach and why?
With the amount of code you show, both approaches are equivalent. That doesn't mean they are equivalent under all circumstances.
synchronized(x) set the lock on x, so in general, you should synchronize using an object common to all threads using shared resources. If threads use a single common resource (such as the list), then synchronizing on that list works. If threads share more than one resource, you have to synchronize on a separate object to control access to those shared resources. This can be an object, or this depending on the context.
synchronized(this) also prevents mutual exclusion among the methods of a class, so that, or synchronized methods are useful if object state needs to be modified in a thread safe manner.
This question already has answers here:
Avoid synchronized(this) in Java?
(23 answers)
Closed 7 years ago.
I am reading the Oracle tutorials about multithreading programming in Java. I don't understand why should I create a new object to sync the some part of code? For what reason does the creation of new dummy object serve?
I do understand that creating these two objects will prevent compiler from reordering the code segment guarded by the construction syncronized(lock1){}
However, I would like to know can I use any other objects (except MsLunch) in the construction syncronized(lock1){} ?
What is the motivation behind introducing such construction syncronized(lock1){} ?
Here is the piece of code, I am concerned with:
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
// what is the purpose of these two objects? how do they serve as locks?
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
First some basics:
The synchronization object is used as a key to open a door to a restricted area (the synchronization block).
As long as a thread entered this restricted area it holds the monitor (lock) so that no other thread can enter. When a thread exits the restricted area it releases the monitor and another thread can take it.
This means that each synchronization block that uses the same synchronization object will prevent other thread to enter until the monitor is available (unlocked).
For what reason does the creation of new dummy object serve?
The reason is that you should use objects that are not accessible by others objects than the ones that use them. That's why the synchronization objects are private. If they would be accessible by others, other might use them in their synchronization blocks somewhere in the application. If the synchronizcation object is e.g. public then every other object can use it. This might lead to unexpected usage and might result in deadlocks.
So you should make sure who will get a reference to the synchronization object.
The lock is accessed by the threads to check if the code is currently "in use" or if they can execute it after locking the object themselves.
You may think it could be automatic, but it has a use compilers couldn't infer : you can use the same lock to synchronize multiple code blocks, restraining the access to any of them at the same time.
In my opinion, dummy Object just represents the point of synchronization.
For synchronize different threads, you must be able to declare point of synchronization and(if it is needed) give access to this point from different parts of the code. For example:
private Object lock = new Object();
public void inc1() {
synchronized(lock) {
c1++;
}
}
public void inc2() {
synchronized(lock) {
c2++;
}
}
In this example shown the usage of same point of synchronization from different part of code.
And because Java is Object oriented language i.e. unit of language in Java is Object, we have exactly such a construction.
By the way, you can use any object in as point of synchronization. You can do even this:
public void inc1() {
synchronized(this) {
c1++;
}
}
what is the purpose of these two objects? how do they serve as locks?
As shown in your code, inc1() and inc2() can only be invoked by one thread each. This means that c1 and c2 can be increased just once per thread - but simultaneuosly by two different threads (because both threads synchronize on different objects).
If both blocks were synchronized like this synchronized(lock1), c1 and c2 could not be increased simultaneuosly.
I have a situation and I need some advice about synchronized block in Java. I have a Class Test below:
Class Test{
private A a;
public void doSomething1(String input){
synchronized (a) {
result = a.process(input);
}
}
public void doSomething2(String input){
synchronized (a) {
result = a.process(input);
}
}
public void doSomething3(String input){
result = a.process(input);
}
}
What I want is when multi threads call methods doSomeThing1() or doSomeThing2(), object "a" will be used and shared among multi threads (it have to be) and it only processes one input at a time (waiting until others thread set object "a" free) and when doSomeThing3 is called, the input is processed immediately.
My question is will the method doSomeThing3() be impacted my method doSomeThing1() and doSomeThing2()? Will it have to wait if doSomeThing1() and doSomeThing2() are using object "a"?
A method is never impacted by anything that your threads do. What gets impacted is data, and the answer to your question depends entirely on what data are updated (if any) inside the a.process() call.
You asked "Variable reference or memory is blocked?"
First of all, "variable" and "memory" are the same thing. Variables, and fields and objects are all higher level abstractions that are built on top of the lower-level idea of "memory".
Second of all, No. Locking an object does not prevent other threads from accessing or modifying the object or, from accessing or modifying anything else.
Locking an object does two things: It prevents other threads from locking the same object at the same time, and it makes certain guarantees about the visibility of memory updates. The simple explanation is, if thread X updates some variables and then releases a lock, thread Y will be guaranteed to see the updates only after it has acquired the same lock.
What that means for your example is, if thread X calls doSomething1() and modifies the object a; and then thread Y later calls doSomething3(), thread Y is not guaranteed to see the the updates. It might see the a object in its original state, it might see it in the fully updated state, or it might see it in some invalid half-way state. The reason why is because, even though thread X locked the object, modified it, and then released the lock; thread Y never locked the same object.
In your code, doSomething3() can proceed in parallel with doSomething1() or doSomething2(), so in that sense it does what you want. However, depending on exactly what a.process() does, this may cause a race condition and corrupt data. Note that even if doSomething3() is called, any calls to doSomething1() or doSomething2() that have started will continue; they won't be put in abeyance while doSomething3() is processed.
I have class with 2 synchronized methods:
class Service {
public synchronized void calc1();
public synchronized void calc2();
}
Both takes considerable time to execute. The question is would execution of these methods blocks each other. I.e. can both methods be executed in parallel in different threads?
No they can't be executed in parallel on the same service - both methods share the same monitor (i.e. this), and so if thread A is executing calc1, thread B won't be able to obtain the monitor and so won't be able to run calc2. (Note that thread B could call either method on a different instance of Service though, as it will be trying to acquire a different, unheld monitor, since the this in question would be different.)
The simplest solution (assuming you want them to run independently) would be to do something like the following using explicit monitors:
class Service {
private final Object calc1Lock = new Object();
private final Object calc2Lock = new Object();
public void calc1() {
synchronized(calc1Lock) {
// ... method body
}
}
public void calc2() {
synchronized(calc2Lock) {
// ... method body
}
}
}
The "locks" in question don't need to have any special abilities other than being Objects, and thus having a specific monitor. If you have more complex requirements that might involve trying to lock and falling back immediately, or querying who holds a lock, you can use the actual Lock objects, but for the basic case these simple Object locks are fine.
Yes, you can execute them in two different threads without messing up your class internals but no they won't run in parallel - only one of them will be executed at each time.
No, they cannot be. In this case you might use a synchronized block instead of synchronizing the whole method. Don't forget to synchronize on different objects.
What is the difference between a Collections.synchronizedMap() and a wrapper around a HashMap with all the methods synchronized. I dont see any difference becuase Collections.synchronizedMap() internally maintains the same lock for all methods.
Basically, what is the difference between the following code snippets
Class C {
Object o;
public void foo() {
synchronized(o) {
// thread safe code here
}
}
}
and
Class C {
Object o;
public synchronized void foo() {
}
}
There is only one difference:
Collections.synchronizedMap is able to use a different monitor than itself.
Using synchronized methods is the same as using sychnchonized(this)-blocks, which means, the wrapper would be the monitor and could be locked from the outside of the wrapper.
If you doesn't want an outside application to lock your monitor, you need to hide it.
On the other side, if you want to call multiple methods in a thread safe fashion, it is the easiest way to lock the whole collection (but it's not very scaleable, indeed).
Ps: For reuse, it's better to delegate the method calls to a backup-Map than to override the class, because you can switch to another Map implementation later, without changing your wrapper.
Both approaches acquire a monitor on the object and so should perform exactly the same. The main reason for the difference is architectural. The synchronized wrapper allows extending the basic non-thread safe variation easily.
Having said that don't use either, use ConcurrentHashMap. It uses lock striping so it's much quicker to use than either approach (as they are the same in terms of overhead + contention). Lock striping allows segments of the backing array to be locked independently. This means it's less probable that two threads will request to acquire the same lock.
Do not reinvent the wheel and use what is provided by the API.
You should always decorate rather than lumping everything and all feartures into one big featured class.
Always take the plain Map and decorate it with Collections or use a java.util.concurrent and use a real lock, so one can atomically inspect and update the map. Tomorrow you might want to change the Hashtable to a Treemap and you will be in trouble if your stuck with a hashtable.
So, why do you ask? :) Do you really believe that if class is placed in java.util package then some magic happens and its java code works in some tricky way?
It really just wraps all methods with synchronized {} block and nothing more.
UPD: the difference is that you have much less chances to make a mistake if you use synchronized collection instead of doing all synchronization stuff by yourself.
UPD 2: as you can see in sources they use 'mutex'-object as monitor. When you use synchronized modifier in method signature (i.e. synchronized void doSmth()) current instance of your object (i.e. this) is used as a monitor. Two blocks of code below are the same:
1.
synchronized public void doSmth () {
someLogic ();
moreLogic ();
}
synchronized public static void doSmthStatic () {
someStaticLogic ();
moreStaticLogic ();
}
2.
public void doSmth () {
synchronized (this) {
someLogic ();
moreLogic ();
}
}
public static void doSmthStatic () {
synchronized (ClassName.class) {
someStaticLogic ();
moreStaticLogic ();
}
}
If thread safety is the case, use concurrency package data structures. Using the wrapper class will reduce all accesses to the Map into a sequential queue.
a) Threads waiting to do operations at totally different points in the Map will be waiting for the same lock. Based on the number of threads this can affect the application performance.
b) Consider compound operations on the Map. Using a wrapper with a Single lock will not help. For example. "Look if present then add" kind of operations. Thread syncronization will again become an issue.