views:

154

answers:

7

Will the _otherThing field below be protected by the locks?

class ThreadSafeThing
{
    private readonly object _sync = new object();

    private SomeOtherThing _otherThing;

    public SomeOtherThing OtherThing { get { lock(_sync) return _otherThing; } }

    public void UpdateOtherThing(SomeOtherThing otherThing)
    {
        lock(_sync) _otherThing = otherThing;
    }
}
A: 

Hi, i am not shure i haven't done anything with threads along time but i think it won't be locked Best Regards, Iordan

IordanTanev
But you felt the need to post here anyway? You're entitled to be wrong on occasion of course, but if you doubt your own knowledge, your answer becomes rather useless :P
Thorarin
+3  A: 

This construction:

lock(_sync) _otherThing = otherThing;

...is the same as this construction:

lock(_sync)
{
    _otherThing = otherThing;
}

So yes, the assignment of _otherThing is protected by the lock.

Fredrik Mörk
+2  A: 

Yes, it will be protected because the _sync object doesn't change.

Edit: The usage of the lock you have here is almost certainly not what you meant, as detailed in several other answers in this thread.

280Z28
That just doesn't seem right...
Svish
@280Z28: if SomeOtherThing is a `struct` the assignment may not be atomic.
Fredrik Mörk
Thanks. My example is trivial just to make it easy to ask.
wizlb
@Fredrik: I can't believe I let that one slip by. Same goes for `double` and `long` on a 32-bit machine.
280Z28
+6  A: 

Yes.

This is not related to lock. C# programs are expressed using statements. Using {} groups multiple statements as a block. A block can be used in the context where a single statement is allowed. See C# language specification section 1.5.

Brian Rasmussen
Thanks for explaining the answer.
wizlb
+1  A: 

As far as I know

lock(_sync)
  _otherThing = otherThing;

is the same as

lock(_sync) _otherThing = otherThing;

is the same as

lock(_sync)
{
  _otherThing = otherThing;
}

Which is similar to

if(something)
  _otherThing = otherThing;

which is the same as

if(something)
{
  _otherThing = otherThing;
}

(And by similar I mean similar in syntax, not in function. if is not the same as lock of course :p)

Actually you can use { } even without a lock, if or anything similar to group statements.

Svish
A: 

Your code is not thread safe, as your dealing with references.

Unless the only thing your lock is preventing is the return of the reference to your object (which is threadsafe without a lock see section 5.5 of the C# language spec) then you will not make changes to the _otherThing threadsafe.

You would need to make your mutators and accessors threadsafe in this instance (by locking around changes and reads of your object).

Spence
Thanks. SomeOtherThing could also be a value type, but I wasn't asking about how to lock things I was asking just about the syntax.
wizlb
SomeOtherThing could also be immutable. The lock *does* have another purpose though, in terms of the memory model.
Jon Skeet
Care to elaborate on that one Jon? I follow if your type is immutable then yes you can give out references without worrying. What memory model effects are you referring to? If you are dealing with a reference type and indeed many of the value types described in 5.5 then you have threadsafe assignment and read, a lock is simply slowing you down.
Spence
@Spence: The assignment is atomic, but not thread-safe - unless you include "there's no guarantee that the reading thread will ever see the new value written by another thread" as thread-safe. You need the field to be volatile, or have other memory barriers (including locks).
Jon Skeet
Ah, you refer of course to caching the value. So you would need to memory barrier or lock to flush that reference out of the cache to main memory on all processors. Concurrent programming is fun... Cheers for your response btw.
Spence
A: 

That will work. Single statements and block statements are pretty much always interchangeable in the C# syntax (except with method bodies and such).

However, it may not even be necessary to do the lock at all. If you want to prevent the property from being changed while other changes are made, then yes. If SomeOtherThing is a value type (struct), you will also need to lock it.

If you chose to not use a lock, you will need to declare the field volatile if you want to make sure your changes are visible in other threads immediately.

Thorarin
Or if you want to make sure that your changes are seen by other threads... generally you need *some* sort of memory barrier when reading or updating shared memory, to ensure appropriate visibility.
Jon Skeet
`volatile` should do for that purpose though. I wanted to add it, but Safari on iPhone 3.0 software really doesn't like Stack Overflow. There you go :P
Thorarin