Suppose that thread Alpha
is writing to variable A
without locking. A second thread Beta
is waiting for Alpha
to terminate, then reads the variable A
in turn.
Is it possible that the contents of A
will not be fresh? Can memory writes be delayed beyond the thread lifetime? Won't the standard mechanism of waiting for thread Alpha
termination implicitly work as a memory barrier?
UPDATE 1
Are there any examples of waiting which does not include a memory barrier?
Almost certainly (the API used to wait for thread termination would need to use memory barriers for its own purposes), but I think for a definitive answer you'll need to talk about the specific threading API being used.
For example, posix makes such a guarantee for pthread_join()
: https://stackoverflow.com/a/3208140/12711
And Win32 documents that it's synchronization APIs to wait on an object (for example, a thread handle) impose memory barriers: http://msdn.microsoft.com/en-us/library/ms686355.aspx
This depends on what guarantees your threading library provides. In particular, pthread_join() is defined to be a memory barrier. In most cases thread joining will involve a memory barrier, but it is not inconceivable that this may not always be the case.
(Assuming you’re referring to C#.)
If you mean Thread
literally, then your answer depends on whether Thread.Join
implicitly generates memory barriers (which, per the answers already given, it probably does).
However, if you mean that Alpha
and Beta
are user-defined tasks executed on a background thread (possibly from the thread pool), and that “waiting” refers to user-level synchronization between the two tasks, then it’s more likely that the data will not be fresh, unless a signaling construct or an explicit barrier is introduced.
Here is a trivial example:
public class Program
{
static string A = "foo";
static volatile bool isAlphaReady = false;
static void Alpha()
{
A = "bar";
isAlphaReady = true;
}
static void Beta()
{
while (!isAlphaReady)
; // Wait by polling
Console.WriteLine(A);
}
static void Main(string[] args)
{
new Thread(Alpha).Start();
new Thread(Beta).Start();
Console.ReadKey();
}
}
Although it appears (intuitively) that Beta
will always output "bar"
as the value of A
, this is not guaranteed on a multiprocessor system with weak synchronization behaviour (such as Itanium), in which case, "foo"
may be output instead.