Donnie,

   Very good explantation. I get it now. Thanks for taking the time.

Chuck

At 10:07 PM 4/15/2002 -0400, you wrote:
>See below.
>
> >
> > You mentioned that the three steps are atomic. To me, atomic means that
> > they all succeed or the operation set fails. I don't think this
> > is the case
> > here. If the lookup finds an action, the other operations are not
> > executed.
> > To me, the atomic part is, if the action is not found in the map:
> > 1)       Start Atomic operation.
> >     2) Create an instance of the Action.
> >     3) Store the instance in the Map.
> >     4) Stop atomic operation.
> >
> > I believe this is the set of operations that should be atomic. By
> > ensuring
> > that these operations succeed without interruption, is the main goal.
>
>First, I mean atomic here in the sense that they all have to occur within a
>sychronized block, not in the database sense of atomicity, succeed-fail etc.
>
>Second, I'll try to more carefully explain the race condition that can occur
>if the synchronization doesn't begin before checking the map. I'll use your
>scenario, which in pseudocode is:
>
>1) Action actn = map.get(actionType);
>2) if (actn == null) {
>3)     synchronized {
>4)         Action actn = new actionType;
>5)         map.put(actionType, actn);
>6)     }
>    }
>    return actn;
>
>We have two threads, "a" and "b" arriving at this code sequence, racing to
>get through; and both threads are interested in the same action type.
>
>Thread "a" executes 1) and 2); then a context switch occurs. At that point,
>there is still not an Action of the appropriate type in the map.
>
>So thread "b" executes 1), 2), and 3); it's got the lock now.
>
>Thread "a" wakes up and tries to do 3), but can't so it blocks.
>
>Thread "b" wakes up again. It executes 4), 5), and 6); now there's an Action
>of the appropriate type in the map, and thread "b" goes merrily on its way.
>
>Thread "a" wakes back up and can now obtain the lock. It executes 3), 4),
>5), and 6). So a second Action of the same action type has been put int the
>map; since HashMap only allows one for a given key, it overwrites the first
>Action that thread "b" had put in there.
>
>Again, in this narrow scenario, it may be acceptable to live with that since
>getting a second one that's functionally equivalent to the first, and
>letting the first get gc'd, isn't a big deal. Another option would be to
>make the map functionally read-only by creating all the Actions at
>initialization time rather than "just-in-time". Not sure of the implications
>of that idea, though.
>
>This precise scenario is one reason why the whole concept of "thread-safe"
>containers like the original HashTable are a bad idea in my opinion. Sure,
>it may make access to the internal data structures safe for the duration of
>any single method call on the object; but it doesn't help any with the
>logical scenarios via which a container is accessed.
>
> >
> > As far as double-check pattern goes, I don't believe moving synchronized
> > down just to around the action create changes anything with respect to
> > double-check. As far as I understand it, the double-check problem
> > has to do
> > with certain optimizing compilers having the freedom to rearrange the
> > creation during a constructor call, and the actual setting of the field
> > reference of the new object that was just created in the constructor. If
> > one thread calls the constructor and an object is created, another thread
> > may check the field reference and not see it because the compiler has
> > rearranged the execution.
>
>I only mentioned the double-check pattern because someone might say that
>that would be a valid optimization, and I wanted to preemptively respond to
>that. :)
>
>Hope that all helps,
>
>Donnie
>
>
>--
>To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
>For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to