Is this Thread-Safe?

  • Thread starter Thread starter Cool Guy
  • Start date Start date
C

Cool Guy

using System;
using System.Threading;

class EntryPoint
{
static void Main() {
Test t = new Test();
t.DoSomething();
}
}

class Test
{
object o;

public void DoSomething() {
o = new Object(); // write to o
new Thread(new ThreadStart(ThreadJob)).Start();
}

void ThreadJob() {
DoSomethingWith(o); // read from o
}
}

------

The only write to /o/ happens before the new thread is created. In the new
thread a read from /o/ happens.

I've been told that a new thread's view of memory is synchronized with that
of the thread that created it. So if this is true I assume this code is
safe (or could the write to /o/ be re-ordered to *after* the new thread's
creation?).
 
Yes, it is.

Threading problem arsie when at least one of the multiple thread running is
doing write acess to a variable.
If everyone only read, as it is the case here (the write occurs before
thread creation) you won't have problem.

Isn't that cool, guy?! ;-)
 
Lloyd Dupont said:
Threading problem arsie when at least one of the multiple thread running is
doing write acess to a variable.
If everyone only read, as it is the case here (the write occurs before
thread creation) you won't have problem.

While I suspect this is actually true, I don't believe it's guaranteed,
unless there's a guarantee of a write memory barrier involve in
creating a new thread.

I can't see anything within the CLI spec which says that the write to o
will be made visible before the other thread starts running.

I would be very surprised if creating a new thread *didn't* involve a
write memory barrier, admittedly...
 
Well Jon, that's difficult to test as x86 has string memory mode so no bug
will never arise ;-)
Anyway if you've got a ia64 architecture handy you could try ;-)

That said I would say, if you're afraid of, go on, call
1. Thread.MemoryBarrier();
2. I *believe* this should be allright, though.... multithreading can't be
THAT crazy.. or could it?


I believe that
 
Lloyd Dupont said:
Well Jon, that's difficult to test as x86 has string memory mode so no bug
will never arise ;-)
Anyway if you've got a ia64 architecture handy you could try ;-)

That said I would say, if you're afraid of, go on, call
1. Thread.MemoryBarrier();
2. I *believe* this should be allright, though.... multithreading can't be
THAT crazy.. or could it?

This is about where I draw the line in practice. I'm far more paranoid
than most people about thread-safety, but I'd go with the assumption
that there's a write barrier when you create the new thread.
 
Jon Skeet said:
This is about where I draw the line in practice. I'm far more paranoid
than most people about thread-safety, but I'd go with the assumption
that there's a write barrier when you create the new thread.

I just hope there doesn't need to be a read barrier every time /o/ is read.

BTW, about this whole multi-threading business -- it seems that no-one
really knows for sure what's safe and what isn't. Is there not some
document which describes all of this?

If not, does anyone know why not? And, if not, is it normal for a
framework's memory model to be so poorly documented?
 
Cool Guy said:
I just hope there doesn't need to be a read barrier every time /o/ is read.

No, there doesn't - so long as its value doesn't change, of course. If
you want to be guaranteed to observe a new value, you'll need a read
barrier.
BTW, about this whole multi-threading business -- it seems that no-one
really knows for sure what's safe and what isn't. Is there not some
document which describes all of this?

There's the CLI specification, which is *fairly* clear once you get
your head round it.
If not, does anyone know why not? And, if not, is it normal for a
framework's memory model to be so poorly documented?

It's documented, but to be *absolutely* safe against *all* possible
conformant CLIs, you have to put a lot of extra work in, like in this
example. It's a sort of sliding scale:

1) There are things which won't work on pretty much any implementation.
2) There are things which will usually work on a single processor.
3) There are things which may work on multi-processor boxes with the
current implementation, but may well not work in the future.
4) There are things (like this example) which are very likely to work
forever, but aren't quite guaranteed.
5) There are things which are absolutely guaranteed.

I usually code to level 4.
 
Jon Skeet said:
No, there doesn't - so long as its value doesn't change, of course. If
you want to be guaranteed to observe a new value, you'll need a read
barrier.

But I suppose that this assumes that a spawned thread has a view of memory
that is synchronized with that of the spawning thread -- which doesn't
appear to be documented.
There's the CLI specification, which is *fairly* clear once you get
your head round it.

Is there anything official other than
<http://www.ecma-international.org/publications/standards/Ecma-335.htm>?
 
Back
Top