Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Wiki Markup
According to the Java API class {{java.lang.ThreadLocal<T>}} documentation \[[API 06|AA. Java References#API 06]\], class {{java.lang.ThreadLocal<T>}} documentation:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

...

The following table shows a possible execution order:

Time

/Thread#

Pool Thread

Submitted By Method

Day

1

t1

1

doSomething1()

Friday

2

t2

2

doSomething2()

Monday

3

t3

1 or 2

doSomething2()

Friday

In this execution order, the two threads (2 t1 and 3 t1) started using doSomething2() are expected to see the current day as Monday, however, one of them (thread t3) inherits the day Friday from the first thread (thread t1), when that thread is reused.

...

This solution transfers the burden of maintainability to the client (DiaryPool) but is a good option when the Diary class cannot be refactored.

...

The class Diary does not use a ThreadLocal object in this compliant solution. Also, the class DiaryPool uses local instances of class Diary within the methods doSomething1() and doSomething2(). The Day is uniquely maintained by each instance of the Diary class. As multiple threads are allowed to share a Diary instance, the day field is declared static. Creating two Diary instances in class DiaryPool allows the first thread to work with the object instance having the current day as Friday and the other two threads to work with the object instance having the current day as Monday.

Code Block
bgColor#ccccff
public final class Diary {
  private staticvolatile Day day;

  Diary() {
    day = Day.MONDAY; // Default	
  }

  private Day currentDay() {
    return day;
  }

  public void setDay(Day d) {
    day = d;
  }

  // Performs some thread-specific task
  public void threadSpecificTask() {
    // Do task ...
  }
}

public final class DiaryPool {
  private final int NoOfThreads = 2; // Maximum number of threads allowed in pool
  private final Executor exec;

  DiaryPool() {
    exec = (Executor) Executors.newFixedThreadPool(NoOfThreads);
  }

  public void doSomething1() {
    final Diary diary = new Diary(); // First instance
    exec.execute(new Runnable() {
      public void run() {
        diary.setDay(Day.FRIDAY);
        diary.threadSpecificTask();
      }
    });
  } 

  public void doSomething2() {
    final Diary diary = new Diary(); // Second instance
    exec.execute(new Runnable() {
      public void run() {
        diary.threadSpecificTask();
      }
    });
  }

  public static void main(String[] args) {
    DiaryPool dp = new DiaryPool();
    dp.doSomething1(); // Thread 1, requires current day as Friday
    dp.doSomething2(); // Thread 2, requires current day as Monday 
    dp.doSomething2(); // Thread 2, requires current day as Monday
  } 
}

Creating two Diary instances in class DiaryPool allows the first thread to work with the object instance having the current day as Friday and the other two threads to work with the object instance having the current day as Monday.

The following table shows a possible execution order that conforms to the requirements:

Time

/Thread#

Pool Thread

Submitted By Method

Day

1

t1

1

doSomething1()

Friday

2

t2

2

doSomething2()

Monday

3

t3

1 or 2

doSomething2()

Monday

Classes that cannot be refactored and whose design incorporates ThreadLocal data should not be executed in thread pools.

Exceptions

EX1: Sometimes the state of the ThreadLocal object does not change beyond its initial value. For example, there may be only one type of database connection represented by the initial value of the ThreadLocal object. In the absence of mutability, it is safe to use a thread pool.

...

When objects of classes that use ThreadLocal data are executed in a thread pool by different threads, they may assume stale statesthe objects might acquire stale values, resulting in corrupt datastate.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON27- J

high

probable

medium

P12

L1

...