Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lock in properties, good approach?

In my multithreading application I am using some variables that can be altered by many instances in the same time. It is weird but it has worked fine without any problem..but of course I need to make it thread-safe. I am just beginning with locks so I would appretiate your advice:

When client connects, class Client is created where each Client has its own "A" variable.

Sometimes, Client calls method like that:

Client selectedClient SelectOtherClientClassByID(sentID);

selectedClient.A=5;

No problems until now with that even when 5 classes were doing at the same time (threadpool), but I was thinking what about adding locks to A properties?

Like:

A {
    get { return mA; }
    set {
        // use lock here for settting A to some value
    }    
}

Would it be OK?

like image 688
Petr Avatar asked Oct 23 '09 09:10

Petr


People also ask

What is a lock property?

The Locked property specifies whether you can edit data in a control in Form view. Read/write Boolean. expression.Locked. expression Required. An expression that returns one of the objects in the Applies To list.

How much work should I place inside a lock statement?

Do as little work as possible while locking a particular object. Locks that are held for a long time are subject to contention, and contention is slow.

What are locks in multithreading?

A lock may be a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: just one thread at a time can acquire the lock and everyone accesses to the shared resource requires that the lock be acquired first.

Why we use lock in C#?

The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.


2 Answers

You need to use locks in BOTH get and set. This lock must be the same object. For example:

private object mylock = new object();

public int A {

  get {
    int result;
    lock(mylock) {
    result = mA; 
    }
    return result;
  } 

  set { 
     lock(mylock) { 
        mA = value; 
     }
  }
}
like image 185
NT_ Avatar answered Sep 20 '22 21:09

NT_


Locking access to properties inside of accessors may lead to bogus results. For the example, look at the following code:

class C {
    private object mylock = new object();

    public int A {

      get {
        int result;
        lock(mylock) {
        result = mA; 
        }
        return result;
      } 

      set { 
         lock(mylock) { 
            mA = value; 
         }
      }
    }
}
C obj = new C;
C.A++;

(yes, I've copied it from the first answer) There is a race condition here! Operation "C.A++" actually requires two separate accesses to A, one to get the value and the other to set the updated value. Nothing ensures that these two accesses will be carried out as together without context switch between them. Classical scenario for race condition!

So, beware! It's not a good idea to put locks inside accessors, locks should be explicitly obtained, like the previous answer suggests (though it doesn't have to be with SyncRoots, any object will do)

like image 27
ilial Avatar answered Sep 20 '22 21:09

ilial