Click here to Skip to main content
15,881,089 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
Hi guys, i came here with one question about efficiency in locking of resource in multi-threading enviroment.

In my class i have a dictionary resource and many methods wich performs differ actions against it.
For providing thread-safety i added a ReaderWriterLockSlim member called _RWLock.
So question consists of next, i've got a method, see below:

C#
try
            {
                _RWLocker.EnterReadLock();
                if (_GameSessionsBankroll.ContainsKey(gameSessionId))
                {
                    long previousBankrol = _GameSessionsBankroll[gameSessionId];
                    try
                    {
                        _RWLocker.EnterWriteLock();
                        _GameSessionsBankroll[gameSessionId] = previousBankrol - amount;
                    }
                    finally
                    {
                        _RWLocker.ExitWriteLock();
                    }
                }
                else
                {
                    try
                    {
                        _RWLocker.EnterWriteLock();
                        _GameSessionsBankroll[gameSessionId] = amount;
                    }
                    finally
                    {
                        _RWLocker.ExitWriteLock();
                    }
                }
            }
            finally
            {
                _RWLocker.ExitReadLock();
            }



Is it correct implementation of thread-safety in case of simultaneous writting and reading data amoung differ thraeds??

Or i just can be bounded by single locking ??
Can anybody explein me which way more efficient in case of performance consideration??
Posted
Updated 23-Aug-12 7:46am
v3

It depends on how to use the locked resources. The reader-writer lock should have some overhead over the regular lock, so you can gain performance if you have the situation when most calls to this fragment of code end up getting only read-only access, and considerably fewer calls get write access. So, the typical scenario is this: some thread passes throw the lock with read access only, read some of data and, depending on the local thread data and the data just read, calculates if write access is needed. Then the thread is promoted to the write access and writes of data, and it happens more or less more rarely than without the write access.

If the scenario is different, or it is uncertain if this is the case or not, using a regular lock could be better.

I think you understand the real throughput depends on many factors, first of all, on you general multithreading code design. The main rule is: "the best lock is no lock". You can greatly reduce mutual locking by doing most processes on stack (avoiding unnecessary static objects, in particular), not sharing resources or reducing the sharing to absolute minimum. In certain cases you can improve performance by passing data throw intermediate conveyors/queues. Even if you use the fastest possible locking mechanism, you can screw it up by lousy architecture of general code design.

—SA
 
Share this answer
 
Comments
Mehdi Gholam 23-Aug-12 14:27pm    
5'ed, agreed "best lock is no lock"
Sergey Alexandrovich Kryukov 23-Aug-12 14:30pm    
Thank you, Mehdi.
--SA
I think a single use of the Write Lock is correct, as you are always doing a write. Try (untested):
C#
try
{
  _RWLocker.EnterWriteLock();
  long previousBankrol;
  if (_GameSessionsBankroll.TryGetValue(gameSessionId, out previousBankrol))
  {
    _GameSessionsBankroll[gameSessionId] = previousBankrol - amount;
  }
  else
  {
    _GameSessionsBankroll[gameSessionId] = amount;
  }
}
finally
{
  _RWLocker.ExitWriteLock();
}
 
Share this answer
 
A really good free reference on Threading, which includes locking is http://www.albahari.com/threading/[^]. Download it now, it is a great reference.
 
Share this answer
 
It's much cleaner to just use lock :
C#
private object _lock = new object();

public void dosomething()
{
   lock(_lock)
   {
      // your code here
   }
}

public void dosomethingelse()
{
   lock(_lock)
   {
      // your code here
   }
}
 
Share this answer
 
Comments
Oleksandr Kulchytskyi 23-Aug-12 14:24pm    
I fully agree with you. The code looks much cleaner.
But if think in way of performance consideration, if one thread wants to read some resource , but another has already locked it resource and tries to write some data, reader thread must wait until another thread will complete its activities agains this resource.
In case of RWLS we locked only specific action types (write , read)
Mehdi Gholam 23-Aug-12 14:27pm    
You can use 2 objects for read and write locks, but if there is a single resource then it would make no difference as you will have to block read and writes as they would interact.
Mehdi Gholam 23-Aug-12 14:28pm    
If it is applicable you can look into ring buffers which don't require locks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900