Reputation: 753
Below is the first code snippet from Java concurrency in Pratice
. I don't get how this class is not thread safe? Won't every time a thread needs to call the method getNext(), it would first create instance of this class? Can two threads share same instance of this class (barring explicit share)?
@NotThreadSafe
public class UnsafeSequence {
private int value;
/** Returns a unique value. */
public int getNext() {
return value++;
}
}
Upvotes: 1
Views: 454
Reputation: 718798
Can two threads share same instance of this class (barring explicit share)?
I think this is this is the root of your misunderstanding.
Basically, if two threads both use the reference to a given instance, they are sharing the instance. It really doesn't matter how they managed to get hold of the reference. There is no real distinction between "explicit" and other ways of sharing the reference.
And the base assumption of the example is that two threads >do< somehow manage to share the instance.
(If they didn't, or indeed if there was only one thread, the thread-safety or otherwise of the class would not be an issue. To use the terminology of Goetz et al, the thread-safety of a "thread confined" object does not matter.)
Upvotes: 2
Reputation: 222
Since Java allow multi-threaded language ( where multiple threads run in parallel to complete program execution ) In multi-threaded environment synchronization of java object or synchronization of java class becomes extremely important.
Synchronization is a feature which allow only one thread can access a resource at a time. It works on the concept of Locking.
ThreadDemo T1 = new ThreadDemo(safeSeq);
ThreadDemo T2 = new ThreadDemo(safeSeq);
In the above code, we are giving here separate lock for both the threads
public class UnsafeSequence {
private int value;
/** Returns a unique value. */
public int getNext() {
return value++;
}
}
class ThreadDemo extends Thread {
UnsafeSequence safeSeq;
public void run() {
some code here
safeSeq.getNext();
}
}
public class TestThread {
public static void main(String args[]) {
UnsafeSequence safeSeq = new UnsafeSequence();
ThreadDemo T1 = new ThreadDemo(safeSeq);
ThreadDemo T2 = new ThreadDemo(safeSeq);
T1.start();
T2.start();
}
}
Upvotes: 0
Reputation: 1709
I don't get how this class is not thread safe?
(You may already now the answer to this, but I include it here for completeness.)
The problem is the value++
statement. It's a multi part statement.
value
is read.value
.This sequence can be intermixed by another thread. Say that value
is 5
. If two threads calls getNext()
(on the same instance), you would expect value
to be 7
when they are done. However, if both threads has done step 1 and 2 before any of the threads do step 3, they will both write the value 6
to value
:
5
5
5
by 1
6
5
by 1
6
Won't every time a thread needs to call the method getNext(), it would first create instance of this class?
Not every time. That would be new UnsafeSequence().getNext()
over and over again, which wouldn't make sense. But perhaps that's not exactly what you meant. Each thread can have their own instance of the class and call getNext()
on that. In that case there is no problem.
Can two threads share same instance of this class (barring explicit share)?
No, an instance must be shared somehow. But it could be shared without you knowing it. E.g., some class may have a static
method that return an instance of UnsafeSequence
. You wouldn't know if it's the same instance that is returned every time or if a new instance is created by each call. Unless this is documented somewhere.
The discussion about if a class is thread safe or not in API documentation refers to cases when an instance is shared between threads. If an instance is not shared, it's OK to use it in a multi threaded application, as long as it's available and used by only one of the threads.
Upvotes: 5
Reputation: 7804
Yes obviously 2 or more threads can access same object at the same time. Thats when race condition occurs i.e. when more than one thread has contention for shared resources (same object of UnsafeSequence
in your case).
EG:
UnsafeSequence seq = new UnsafeSequence();
// both thread instances share same object
Thread t1 = new MyThread(seq);
Thread t2 = new MyThread(seq);
t1.start();
t2.start();
// run method for above `MyThread` class:
public void run() {
while(some condition) {
// some work
System.out.println(seq.getNext()); // sequence is unpredictable
}
}
Had different threads accessing different object instances, there would be no thread safety issue.
Upvotes: 1