Solved

Thread Safe: Generic Dictionary

Posted on 2009-05-05
17
854 Views
Last Modified: 2013-12-17
Hi!

I need to make my generic dictionary  thread-safe

Is this enuff for doing that?
private object _lockServolist = new object();
 

        private Dictionary<string, ServoMotor> Servolist

        {

            get 

            {

                lock (_lockServolist)

                {

                    return this._servoList;

                }

            } 

        }

Open in new window

0
Comment
Question by:AWestEng
  • 6
  • 6
  • 5
17 Comments
 
LVL 39

Accepted Solution

by:
abel earned 250 total points
ID: 24305641
This is not a trivial question to answer. What you are showing is a lock during the get operation. This is not necessary, as when you only need read-access there's no need to lock, unless you want read/write access from multiple threads. Here's what MS has to say about Dictionaries, maybe you need not do anything:

A Dictionary<(Of  <(TKey, TValue>)>) can support multiple readers concurrently, as long as  the collection is not modified. Even so, enumerating through a collection is  intrinsically not a thread-safe procedure. In the rare case where an enumeration  contends with write accesses, the collection must be locked during the entire  enumeration. To allow the collection to be accessed by multiple threads for  reading and writing, you must implement your own synchronization.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 24307962
I can tell you that code is 100% not what you want. Can you put up the code that is calling that code? You generally need locks when you are *using* the dictionary ... all you have done is locked around returning it to the thing that will use it.
0
 
LVL 1

Author Comment

by:AWestEng
ID: 24312139
I read data from the dictionary  in several diffrent methods, but I do not modify the it when multiple threads are accessing the dictionary .
So then it should be safe?
 I do this in about 10 diffrent methods

ServoMotor servo = this._servoList[name];
thre is one time it can create a problem, I have a remove method thats removes a a servo from the list.
 
can i "safe" this up in any way, can I lock with the object "this" in this methd?
0
 
LVL 39

Expert Comment

by:abel
ID: 24312183
If you do not change the Dictionary while reading from it, you should not need a lock. If you want to change the Dictionary and expect other threads to read at the same time, you will need a lock, but on the whole dictionary. If you do not want to block the other threads while removing elements from the Dictionary, you will have to create your own synchronization scheme for the Dictionary.
0
 
LVL 39

Expert Comment

by:abel
ID: 24312193
> you should not need a lock.
means: you do not need a lock.
0
 
LVL 1

Author Comment

by:AWestEng
ID: 24312223
one general thing, so if i have a class object and modify values in this object it does not help to lock the "hole" object in a get property,  it needs to be protected inside the object it self to get the thread-safe ability
 is that right?
0
 
LVL 39

Expert Comment

by:abel
ID: 24312258
since this is not a trivial discussion and not trivial to answer, I think a little example says more then the well-known 1000 words: http://stackoverflow.com/questions/157933/whats-the-best-way-of-implementing-a-thread-safe-dictionary-in-net
0
 
LVL 1

Author Comment

by:AWestEng
ID: 24312696
One other strange this.
In this property I can't lock all in the set part then then hole application stops
and I get a System.ExecutionEngineException
Thre is one thread that is updating but several threads that are reading, so can I do that then?

        public bool Status_StateMotionStoppingSTorLimSW

        {

            get

            {

                lock (_lockStateMotionStoppingSTorLimSW)

                {

                    return this._stateMotionStoppingSTorLimSW;

                }

            }

            set

            {

                lock (_lockStateMotionStoppingSTorLimSW)

                {

                    this._stateMotionStoppingSTorLimSW = value;

                }

                    if (this._previousStateMotionStoppingSTorLimSW != value)

                    {

                        this._previousStateMotionStoppingSTorLimSW = value;
 

                        if (ServoUpdated != null)

                        {

                            ServoUpdated(this);

                        }

                    }

                    else

                    {

                        this._previousStateMotionStoppingSTorLimSW = value;

                    }

               

            }

        }

Open in new window

0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 1

Author Comment

by:AWestEng
ID: 24312716
abel:

 I'm looking at the page you posted, but one post says that the dictionary should be locked

lock (mySafeDictionary)
{
    if (!mySafeDictionary.ContainsKey(someKey))
    {
        mySafeDictionary.Add(someKey, someValue);
    }
}

but what I can remember locking the object itself is not a good idea?
0
 
LVL 39

Expert Comment

by:abel
ID: 24312922
That post apparently contained some inconsistencies and I should've read it through better before posting it here. Here's a more elaborate example that I believe you can just takeover and use for your own: http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 24315491
For your latter code of

        public bool Status_StateMotionStoppingSTorLimSW
        {
            get
            {
                lock (_lockStateMotionStoppingSTorLimSW)
                {
                    return this._stateMotionStoppingSTorLimSW;
                }
            }
            set
            {
                lock (_lockStateMotionStoppingSTorLimSW)
                {
                    this._stateMotionStoppingSTorLimSW = value;
                }
                    if (this._previousStateMotionStoppingSTorLimSW != value)
                    {
                        this._previousStateMotionStoppingSTorLimSW = value;
 
                        if (ServoUpdated != null)
                        {
                            ServoUpdated(this);
                        }
                    }


You are locking on a boolean ... a boolean is a value object... As such it will be boxed and you will be locking on the boxed version (which will be different in both calls...) Create a separate object private object stateLockObject = new object(); and lock on that in both places instead.


0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 24315522
How often are you changing items in the dictionary? is performance a concern?


The easiest way to handle this would be to stop returning the dictionary (generally not considered good practice anyways) and instead put methods on your object for the find and remove. Then just lock in both the find and the remove and you are done.

Greg
0
 
LVL 1

Author Comment

by:AWestEng
ID: 24316626
no i'm lockihn on a object
 _lockStateMotionStoppingSTorLimSW is a object not a bool
0
 
LVL 37

Assisted Solution

by:gregoryyoung
gregoryyoung earned 250 total points
ID: 24316725
sorry misread with all of the similar variable names ... I also didn't see ExecutionEngineException ... this is when the CLR runs into an internal problem http://msdn.microsoft.com/en-us/library/system.executionengineexception.aspx

this is probably not only caused by your bad locking code ... are you using unmanaged code as well (or integrating with an unmanaged dll?)
0
 
LVL 1

Author Comment

by:AWestEng
ID: 24316963
your right there, the ExecutionEngineException  does not seem to have something to do with the locking stuff, I did a clean on the project and the it worked again.
 
0
 
LVL 39

Expert Comment

by:abel
ID: 24318436
Ah, glad to see that gregoryyoung is back on this thread, he's a bit better equipped when it comes to multi threading then I am ;-). You're in good hands there!
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 24319069
The rest of this I think is solved? not sure?
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

IP addresses can be stored in a database in any of several ways.  These ways may vary based on the volume of the data.  I was dealing with quite a large amount of data for user authentication purpose, and needed a way to minimize the storage.   …
In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now