0

Here is a question that has been asked many times, I have double-checked numerous issues that have been raised formerly but none gave me an answer element so I thought I would put it here.

The question is about making my code thread-safe in java knowing that there is only one shared variable but it can change anytime and actually I have the feeling that the code I am optimizing has not been thought for a multi-threading environment, so I might have to think it over...

Basically, I have one class which can be shared between, say, 5 threads. This class has a private property 'myProperty' which can take 5 different values (one for each thread). The problem is that, once it's instantiated by the constructor, that value should not be changed anymore for the rest of the thread's life.

I am pretty well aware of some techniques used to turn most of pieces of code "thead-safe" including locks, the "synchronized" keyword, volatile variables and atomic types but I have the feeling that these won't help in the current situation as they do not prevent the variable from being modified.

Here is the code :

// The thread that calls for the class containing the shared variable //

public class myThread implements Runnable {

     @Autowired
     private Shared myProperty;

     //some code
}

// The class containing the shared variable //

public class Shared {

      private String operator;
      private Lock lock = new ReentrantLock();

      public void inititiate(){
           this.lock.lock()
           try{
                 this.operator.initiate() // Gets a different value depending on the calling thread
           } finally {
                 this.lock.unlock();
           }
      } 

      // some code        
}

As it happens, the above code only guarantees that two threads won't change the variable at the same time, but the latter will still change. A "naive" workaround would consist in creating a table (operatorList) for instance (or a list, a map, etc. ) associating an operator with its calling thread's ID, this way each thread would just have to access its operator using its id in the table but doing this would make us change all the thread classes which access the shared variable and there are many. Any idea as to how I could store the different operator string values in an exclusive manner for each calling thread with minimal changes (without using magic) ?

J. Valjean
  • 35
  • 7
  • 1
    I am not sure what you are trying to accomplish? You want to uniquely identify threads? – Elias Oct 14 '19 at 11:51
  • So do you have (or want) one instance of `Shared` (in which case, the `myProperty` cannot take 5 values), or 5 instances of `Shared` (in which case, is that how you've set Spring to Autowire?) – racraman Oct 14 '19 at 11:53
  • @Elias : I want each thread to see a different value for Shared#operator – J. Valjean Oct 14 '19 at 11:57
  • @racraman : I want one instance of Shared for all 5 threads and for each thread to see a different value in myProperty - About Spring, I have not built the software I am only optimizing it but I am interested in knowing how to set Spring to autowire ! (If I had to guess I'd say that it has been set to autowire one instance of Shared for all the threads) – J. Valjean Oct 14 '19 at 12:00
  • 2
    Ah, the term you are looking for is "thread local". – Elias Oct 14 '19 at 12:00
  • 1
    You guess right - Spring defaults to Singleton scope (some interesting reading here : https://stackoverflow.com/questions/31629993/is-spring-default-scope-singleton-or-not/31630098#31630098 ). For this question, yes - ThreadLocal is the way to go. – racraman Oct 14 '19 at 21:53

2 Answers2

3

I'm not 100% sure I understood your question correctly, but I'll give it a shot anyway. Correct me if I'm wrong.

A "naive" workaround would consist in creating a table (operatorList) for instance (or a list, a map, etc. ) associating an operator with its calling thread's ID, this way each thread would just have to access its operator using its id in the table but doing this would make us change all the thread classes which access the shared variable and there are many.

There's already something similar in Java - the ThreadLocal class?

You can create a thread-local copy of any object:

 private static final ThreadLocal<MyObject> operator =
     new ThreadLocal<MyObject>() {
         @Override 
         protected MyObject initialValue() {
             // return thread-local copy of the "MyObject"
     }
 };

Later in your code, when a specific thread needs to get its own local copy, all it needs to do is: operator.get(). In reality, the implementation of ThreadLocal is similar to what you've described - a Map of ThreadLocal values for each Thread. Only the Map is not static, and is actually tied to the specific thread. This way, when a thread dies, it takes its ThreadLocal variables with it.

Malt
  • 28,965
  • 9
  • 65
  • 105
2

I'm not sure if I totally understand the situation, but if you want to ensure that each thread uses a thread-specific instance for a variable, the solution is use a variable of type ThreadLocal<T>.

Luis Iñesta
  • 401
  • 3
  • 6