Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#4.0 Threading .NET4
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:
 
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 23-Aug-12 8:29am
Edited 23-Aug-12 8:46am
v3
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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
  Permalink  
Comments
Mehdi Gholam at 23-Aug-12 14:27pm
   
5'ed, agreed "best lock is no lock"
Sergey Alexandrovich Kryukov at 23-Aug-12 14:30pm
   
Thank you, Mehdi.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

I think a single use of the Write Lock is correct, as you are always doing a write. Try (untested):
try
{
  _RWLocker.EnterWriteLock();
  long previousBankrol;
  if (_GameSessionsBankroll.TryGetValue(gameSessionId, out previousBankrol))
  {
    _GameSessionsBankroll[gameSessionId] = previousBankrol - amount;
  }
  else
  {
    _GameSessionsBankroll[gameSessionId] = amount;
  }
}
finally
{
  _RWLocker.ExitWriteLock();
}
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 5

A really good free reference on Threading, which includes locking is http://www.albahari.com/threading/[^]. Download it now, it is a great reference.
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

It's much cleaner to just use lock :
private object _lock = new object();
 
public void dosomething()
{
   lock(_lock)
   {
      // your code here
   }
}
 
public void dosomethingelse()
{
   lock(_lock)
   {
      // your code here
   }
}
  Permalink  
Comments
Oleksandr Kulchytskyi at 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 at 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 at 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)

  Print Answers RSS
0 OriginalGriff 505
1 Maciej Los 309
2 BillWoodruff 174
3 /\jmot 160
4 Suraj Sahoo | Coding Passion 160
0 OriginalGriff 8,654
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,639
3 Maciej Los 5,229
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web01 | 2.8.1411023.1 | Last Updated 23 Aug 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100