Re: WaitForSingleObject() will not deadlock

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Fri, 06 Jul 2007 21:47:51 -0400 Joseph M. Newcomer <newcomer@xxxxxxxxxxxx> wrote:
********************

It makes sense. Here's an illustration of what it's saying:

int x = 0; // global

***** Thread 1:

x = 2;
CreateThread;
// x = 3;

***** Thread 2:

if (x == 2)
puts("x == 2");

A. Rule (1) guarantees that when started, thread 2 observes x == 2, since
thread 1 set it to 2 before creating the second thread.
****
Yes, that would be true, if you don't have any other assignments
possible in any other thread. Essentially, there is an algorithmic
guarantee of data stability in such a case, and consequently, it
would not make sense for the thread to see a value OTHER than 2,
because the language semantics would insist that the assignment has
taken place at a time before launching the thread. Any hardware,
software, or compiler optimization that violated this would
represent an incorrect implementation of the language.
*****

No. Even though the assignment of value 2 (in thread 1) is guaranteed
to occur before the execution of "CreateThread" (this is the
compiler's guarantee), without the specific guarantee from the thread
specification that the new thread (thread 2) will see values written
before it was created, the *compiler* does not guarantee this. The
compiler only guarantees that *the thread which set x=2 and then
called "CreateThread"* will see x=2. For example, if CreateThread
modifies the value of x, the compiler guarantees that upon return from
CreateThread, thread 1 sees the new value of x. But just from the
compiler's guarantees, thread 2 is allowed to see the original value
of x=0, because the compiler does not guarantee when changes to data
are visible to other threads. This would not be broken and would
not be a violation, and in fact the compiler has no way to enforce
visibility.

But the posix threads guarantee requires that pthread_create()
execute a membar. *That* is what makes the value of x visible
*to the new thread*.

B. However, if you were to uncomment the line that sets x to 3, thread 2
might not see that value, even if it were executed before thread 2 got
around to testing it. That is, thread 2 might still observe the value 2,
even though from thread 1's perspective, x contains 3, at the moment thread
2 tested it.
****

No, you would definitely see the value 3. The question is WHEN you
would see it. Because we no longer have a guarantee of data
stability, the sequence could be

x=0
x=2
createthread
x=3

and the thread has the sequence
?=x

Now the issue is nondeterministic. Once the thread is launched, it
MIGHT see the value 2, if the assignment x=3 has not been performed,
or it MIGHT see the value 3, if the assignment x=3 has been
performed.

No. Even if the assignment x=3 has been performed in thread 1 before
thread 2 starts running, it is NOT guaranteed to be visible to thread 2.
It is not the point at which thread 2 starts running at which data
is guaranteed to be visible, it is the point at which the thread was
created.

This rule is meant to emphasize non-deterministic thread scheduling,
and to make clear the point at which a membar (associated with
pthread_create()) must be executed.

If you had two threads t1 and t2 and they executed like this:

t1 t2
x=1
x=2
y=x

you are already aware that y in t2 might not be the value 2. This
is NOT because of ordering of instructions in time (note: assignment
y=x is AFTER x=2), it is because there is no guarantee of memory
visibility across threads without explicit synchronization. Now
if you have

t1 t2
DNE
x=1
create
created (x=1 visible)
x=2 starts running
y=x

this adds the thread creation into the mix, however you can see that
this is just like the previous case, and y=2 is not guaranteed.

1. Whatever memory values a thread can see when it creates a
new thread can also be seen by the new thread once it
starts. Any data written to memory after the new thread is
created may not necessarily be seen by the new thread, even if
the write occurs before the thread starts.

*****
No, that is what is confusing. If the write takes place, there is
no reason the new thread will not see it, because the write is
taking place to the location where the variable is found. The issue
is merely the relative timings of when the write takes place. The

No. The new thread might not see it because without explicit
synchronization, data is not guaranteed to be visible across threads,
regardless of time ordering.

suggestion that the write would not be visible if it happened before
the thread starts seems odd, because that would suggest that the
thread gets a local copy of the variable, and that the
implementation reserves the right to make the copy early (at thread
creation) or late (at thread startup). But why would a threaded

It doesn't suggest copies at all. It is about memory visibility.

implementation feel any need to worry about the time a copy is made
when the semantics of the language do not require that a copy be
made at all, and for that matter, would actually "teach against"
this practice?

A memory address is a memory address. Data written to that address
appears in memory. Caches are mechanisms to optimize performance
while giving the illusion of those semantics being maintained.

x=3 does not mean data is written to memory.

-frank
.



Relevant Pages

  • Re: C#, Threads, Events, and DataGrids/DataSets
    ... JIT compiler just compiles IL to x86 (or whatever platform it is developed ... optimization theory if you are interesting). ... then volatile could be important to guarantee that all memory writes ...
    (microsoft.public.dotnet.general)
  • Re: shared memory between processes
    ... POSIX, for example, states several conditions under which memory visiblity ... and not one of them uses or requires 'volatile'. ... mechanisms already guarantee thread safety.) ... compiler no knowledge of the functions, thus the compiler must assume they ...
    (comp.os.linux.development.system)
  • Re: WaitForSingleObject() will not deadlock
    ... sure that results are in memory. ... lock is guaranteed to issue a membar, not because of cache coherency. ... Microsoft C/C++ compiler is very conservative about code motions ... A mutex is sufficient to guarantee visibility, ...
    (microsoft.public.vc.mfc)
  • Re: A basic (?) problem with addresses (gcc)
    ... assignment to y was optimised out; it looks like the compiler didn't ... most likely what the compiler has optimized away is not ... of an int to memory and then re-interpreting those bytes as a float, ... These are exactly the kind of optimizations that the aliasing rules in ...
    (comp.lang.c)
  • RE: .NET SUCKS --- READ FOLLOWING. MICROSOFT IS A SUCKY CO
    ... Any application that must guarantee a response 100% of the time within 1 ... PREALLOCATE all memory you need, ... If your response time requirements are 1 second, ... The app has to respond to the requests in no more than 1 s. ...
    (microsoft.public.dotnet.framework)