Any Good Reference material on Threading?

Posts   
 
    
wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 04-Nov-2004 12:13:23   

Hi All

I have singleton class in my BL library written in VB.Net - How do i go about making it threadsafe?

I know about SyncLock but i am not entirely sure when to use it.

I am sure my questions are very basic. For Example:

If a method in this shared class does a for loop through an array - do i need to make it threadsafe using SyncLock?

Can Thread 2 influence Thread 1's position in the for - loop.

What if this class has a property that can be set - and this property gets used by a method in the class. How do i prefent Thread 2 from tampering with the property after thread 1 has set it?

What needs to happeng is:

Thread 1 : Set property Thread 1 : call method that uses property.

But i am worried that the following can happen,

Thread 1 : Set property

Thread 2 : Set property

Thread 1 : call method that uses property.

Thread 2 : call method that uses property.

Please let me know if know about any articles or other good reference material on the net.

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 04-Nov-2004 15:22:26   

I have been spending alot of time today reading about singletons and thread safety.

Some good reading:

http://blogs.msdn.com/cjohnson/archive/2004/06/10/152179.aspx http://www.yoda.arachsys.com/csharp/singleton.html http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/singletondespatt.asp http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx

But some things are still not clear to me.

Lets say this is my singleton below:

The creation is thread safe but what about the method Foo? confused Do i have to worry about the method? or is only the creation needed to be threadsafe?

If 2 threads have a reference to the same singleton won't they interfere with each other when they both call the method Foo in the same instance of the object?

And how do i make the combination of property X and method Foo2 thread safe?

public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object padlock = new object();
    private int[] _items;
    private int _X;

    Singleton()
    {
    }

        public int X
        {
             get 
             {
                   return X; 
             }
             set 
             {
                 X = value;
              }
        } 

    public int Foo(int item)
    {
      int i;
        for (i=0;i <= _items.Length -1; i++)
        {
            if (_items[i] = item)
            {
              return i;
            }
        }
        return -1;
    }  

    public int Foo2()
    {
            return _X + 1;
    }  

    public static Singleton Instance
    {
        get
        {
            if (instance==null)
            {
                lock (padlock)
                {
                    if (instance==null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}
swallace
User
Posts: 648
Joined: 18-Aug-2003
# Posted on: 04-Nov-2004 15:27:37   
Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 04-Nov-2004 15:43:25   

swallace wrote:

and my favorite place to leech code:

Im gonna troll a bit, dont feel bad about leeching from them, because they leeched their portal from DNN. stuck_out_tongue_winking_eye

MarcoP avatar
MarcoP
User
Posts: 270
Joined: 29-Sep-2004
# Posted on: 04-Nov-2004 17:45:31   

wayne wrote:

And how do i make the combination of property X and method Foo2 thread safe?

You will have to do your same locking code in each of those members, like you did in your singleton entry point. Locking can be a little slower, so I would make sure you really need this extra effort before committing to it.

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 05-Nov-2004 10:41:23   

Frans, any input? Do iu have to add locking into every method and property of the singleton?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39826
Joined: 17-Aug-2003
# Posted on: 05-Nov-2004 10:59:31   

multi-threading is very simple: multiple execution position pointers are walking the code at any given time. This means that a routine can be at statement 10 for thread A but at statement 1 for thread B.

This is not harmful, it works well. The ONLY problem there is is that multiple threads have access to the same variables: member variables (local variables in methods are allocated on the stack, so each thread has its own copy, but BEWARE! in the case of a reference to an object, they both have a copy of the REFERENCE, i.e.: both point to the same object!). So if you have a method M which modifies a given member variable, and thread A and B are both executing M, then both can change that member variable and will do so DURING execution of M.

So to make sure a section of code is executed by just 1 thread, you mark it as a 'critical section'. This means that just 1 thread may enter/be in that section at any given time. You do that by placing mutexes in front of the section, or locks: a thread may only proceed if it is granted the mutex/lock, otherwise it has to wait for its turn.

So you FIRST have to determine what the critical sections of your code are: these are sections which have to be atomic. Dull example:


_isValid = CheckIfIsValid(someVar);   // A
if(_isValid && someBoolean) // B
{
// do things
}

Lines A and B are part of the single atomic action. You can't see them apart from eachother, because what if thread X executes line A, then the thread Y is given execution time, it runs also line A and _isValid gets a different meaning, after that X is again executing the code and B will not be correct.

So any manipulation of member variables and control flow based on the results of that manipulation are part of the same atomic action. You then have to lock that section. For the rest, it's no big deal.

Locking is done by defining a local object variable of type object, and to lock that. That's the most efficient way.

Often you don't need multi-threading however. Multithreading is only useful (in 99% of the cases) for spawning worker threads doing work while you're waiting for the results and have to be responsive to messages/data from the outside.

Frans Bouma | Lead developer LLBLGen Pro
MarcoP avatar
MarcoP
User
Posts: 270
Joined: 29-Sep-2004
# Posted on: 05-Nov-2004 14:32:21   

Otis wrote:

This is not harmful, it works well. The ONLY problem there is is that multiple threads have access to the same variables: member variables (local variables in methods are allocated on the stack, so each thread has its own copy, but BEWARE! in the case of a reference to an object, they both have a copy of the REFERENCE, i.e.: both point to the same object!).

Just to make sure I understand this correctly, if for example, I have a method that has a local data access adapter reference, if ThreadA and ThreadB execute this method at the same time, they are both using the same adapter reference (I was under the impression they both had there own type reference)?


Private void ExecuteMe()
{
    DataAccessAdapter a = new DataAccessAdapter();
    a.FetchEntity(...);
}

So, since the data access adapter object is not thread safe, this code could possible cause problems.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39826
Joined: 17-Aug-2003
# Posted on: 05-Nov-2004 15:06:42   

MarcoP wrote:

Otis wrote:

This is not harmful, it works well. The ONLY problem there is is that multiple threads have access to the same variables: member variables (local variables in methods are allocated on the stack, so each thread has its own copy, but BEWARE! in the case of a reference to an object, they both have a copy of the REFERENCE, i.e.: both point to the same object!).

Just to make sure I understand this correctly, if for example, I have a method that has a local data access adapter reference, if ThreadA and ThreadB execute this method at the same time, they are both using the same adapter reference (I was under the impression they both had there own type reference)?


Private void ExecuteMe()
{
    DataAccessAdapter a = new DataAccessAdapter();
    a.FetchEntity(...);
}

So, since the data access adapter object is not thread safe, this code could possible cause problems.

In that case, they both have another copy because you create two copies simple_smile

if you do this: SomeType t = (SomeType)_memberList[index]; // do something with t

then both reference the same object, however with different variables.

Frans Bouma | Lead developer LLBLGen Pro
MarcoP avatar
MarcoP
User
Posts: 270
Joined: 29-Sep-2004
# Posted on: 05-Nov-2004 15:22:09   

Gotcha, thanks! sunglasses