简体   繁体   中英

Thread safe : Instance of class

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++;
}
 }

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.

  1. The value of value is read.
  2. The read value is incremented by one.
  3. The new value is stored in 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 :

  • Thread 1 do step 1 - reads 5
  • Thread 2 do step 1 - reads 5
  • Thread 2 do step 2 - increment 5 by 1
  • Thread 2 do step 3 - saves the value 6
  • Thread 1 do step 2 - increment 5 by 1
  • Thread 1 do step 3 - saves the value 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. Eg, 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.

Yes obviously 2 or more threads can access same object at the same time. Thats when race condition occurs ie 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.

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 for a "thread confined" object does not matter.)

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();

     }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM