3

I read somewhere that starting a thread has some special effect on the happend before relationship. Now I'm not sure if my code gurantees the happend before relationship, so please enlighten me.

I have a Dispatcher thread and a Worker class implementing the Runnable interface. The Dispatcher thread creates a new instance of the Worker and fills a LinkedList in the Worker instance through the add method with elements.

Then the Dispatcher hands the Worker instance to a ExecutorService via the execute method.

Then the run method in the Worker class starts accessing and removing stuff from the LinkedList.

Does the freshly started instance of the Worker see the same state of the LinkedList as the Dispatcher left it in? Or could it be that LinkedList is in some inconsitent state? Will I have to fill the LinkedList in a sychronized method?

Franz Kafka
  • 10,623
  • 20
  • 93
  • 149

3 Answers3

4

According to the documentations: ExecuterService javadocs

Memory consistency effects: Actions in a thread prior to the submission of a Runnable or Callable task to an ExecutorService happen-before any actions taken by that task, which in turn happen-before the result is retrieved via Future.get().

This means that your concept is correct.

Erel
  • 1,802
  • 2
  • 15
  • 58
2

The Java Language Specification writes:

An action that starts a thread synchronizes-with the first action in the thread it starts.

If an action x synchronizes-with a following action y, then we also have hb(x, y).

If we have two actions x and y, we write hb(x, y) to indicate that x happens-before y.

However, from your description it is not clear whether that is relevant in your case, as you talk about an executor, but don't explain when that executor is created or its worker threads started.

What is relevant is the following exerpt from Executor's JavaDoc:

Memory consistency effects: Actions in a thread prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread.

Hence your code is safe, as long as the dispatcher thread no longer accesses the list after submitting the Runnable.

meriton
  • 68,356
  • 14
  • 108
  • 175
1

If there is locking or other synchronization primitives used, and you're just using a plain old ArrayList, then the two threads could see different states.

When coordinating work between two separate threads, you have to either use a thread-safe/concurrent data structure or use synchronization code to guarantee a consistent "memory snapshot" between the threads.

One of the reasons this is important is due to caching. The two threads, executing concurrently on different processors, could have cached some objects in different local registers (that are local to those processors).

ripper234
  • 222,824
  • 274
  • 634
  • 905
  • Thanks, I though so. But the dispatcher shall never touch the data again. Would it be enough to pass a freshly created LinkedList through the constructor Worker(LinkedList blahBlah). Constructors make a happend before relationship, don't they? – Franz Kafka Oct 04 '11 at 16:48
  • @Franz - Why not just let the worker thread create the lists, if all the dispatcher does is construct them? I'm not entirely sure if constructors do make a happened-before relation. In principle you might be right. – ripper234 Oct 04 '11 at 17:09
  • Damn, I was quite good at this stuff, it's amazing how fast knowledge rusts if left unused. – ripper234 Oct 04 '11 at 17:10