3

I am new to C#. In Java, I can make read/write of a Java class member by having 'synchronized' keyword in the setter/getter method.

Can you please tell me what is the right way to do the same in C#? In C# there is no synchronized keyword. Should I use '[MethodImpl(MethodImplOptions.Synchronized)] annotation' mentioned in C# version of java's synchronized keyword??

Or use Monitor.Enter (and subsequently Monitor.Exit)?

Community
  • 1
  • 1
n179911
  • 19,547
  • 46
  • 120
  • 162
  • 1
    This heavily depends on what kind of a property you're trying to read/write. You can try using the `Interlocked` functions or `lock` (which is just C# syntactic sugar over `Monitor`). – xxbbcc Nov 13 '15 at 02:31
  • You can use the `MethodImpl` attribute, but if the setter isn’t doing anything other than setting a field and the getter isn’t doing anything other than retrieving it, then there’s nothing to synchronize. – Ry- Nov 13 '15 at 02:32
  • try to look at this thread: http://stackoverflow.com/questions/27344873/which-way-is-the-best-for-thread-synchronization/27345090#27345090 also depends on what you do, there are some async-await lock which i highly recommend https://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim(v=vs.110).aspx – Xiaomin Wu Nov 13 '15 at 02:37

3 Answers3

4

Use Monitor.Enter/Exit (or lock - a syntactic sugar for Monitor) with private object _lock = new object() field.

Don't use MethodImplOptions.Synchronized. It locks on this, so it's possible that some other code will lock on the same instance causing deadlocks.

Locking on the instance or on the type, as with the Synchronized flag, is not recommended for public types, because code other than your own can take locks on public types and instances. This might cause deadlocks or other synchronization problems.

Jakub Lortz
  • 14,616
  • 3
  • 25
  • 39
4

In some scenarios, volatile might be sufficient (although it depends what you are guarding against and what the data-type is):

private volatile int _counter;
public int Counter
{
    get { return _counter; }
    set { _counter = value; }            
}

OR lock it

#region public int Counter { set; get; }
private int _counter;
private object sync_counter = new object();
public int Counter
{
    set
    {
        lock(sync_counter)
        {
            _counter = value;
        }
    }
    get
    {
        lock(sync_counter)
        {
            return _counter;
        }
    }
}
#endregion
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
Mingo.Link
  • 168
  • 5
  • Thanks. What is the meaning of '#region public int Counter { set; get; }'? – n179911 Nov 13 '15 at 04:46
  • @n179911 it is just there to allow simple expand/collapse in the IDE; up to you whether you like that type of thing... – Marc Gravell Nov 13 '15 at 07:58
  • 3
    @HungPV I'm not sure it is... any synchronization scenario really needs awareness of what is being protected against what; it could be that `Interlocked` or `volatile` does everything needed here, but more efficiently. – Marc Gravell Nov 13 '15 at 08:00
  • @HungPV I perhaps should advise great caution with `volatile` - it is very subtle, and the way in which it is *usually used* is very different to its stated definition and intent in the language specification (which: most of the people using it would be unable to state - it actually has to do with instruction re-ordering!); but it *can* be used in cases like this one: https://msdn.microsoft.com/en-us/library/x13ttww7.aspx (link shows common usage, not the confusing language specification terminology) – Marc Gravell Nov 13 '15 at 08:14
  • Re edit 3: `public volatile int Counter { set; get; }` is not valid C#, and re edit 2: public fields are to be avoided (/cc @HungPV) – Marc Gravell Nov 13 '15 at 08:20
3

As Lortz said the best way is to use lock

public class ThreadSafeSetters
{
    private bool _foo;
    private object _locker = new object();

    public bool Foo
    {
        get
        {
            lock (_locker)
            {
                return _foo;
            }
        }
        set
        {
            lock (_locker)
            {
                _foo = value;
            }
        }
    }
}
Rustam Safin
  • 812
  • 7
  • 15