Click to See Complete Forum and Search --> : avoiding thread conflicting


Red Squirrel
January 28th, 2008, 08:10 PM
What is the best practice to avoid thread conflicting? For example lets say I have this:




ArrayList arraylist;

Thread1()
{



while(true)
{
usleep(1);
if(arraylist.Size()<0)continue;

DoStuff(&arraylist);

}


}

Thread2()
{

while(something)
{
usleep(1)
arraylist.Add(stuff);
}


}

Thread3()
{

while(true)
{
RandomlyEmpty(&arraylist);
}

}






Ok so basically thread1 does some stuff to arraylist, we'll say it pops values out and reads them, when its empty, it just waits.

Thread2 puts data in arraylist. So these two threads should work well together, BUT what happens if in thread2 when the size evaluates to 1 but at that exact same time, before it does processing, thread3() empties it. Now the DoStuff(&arraylist); will have an empty array list, and we don't want that (lets just say it would crash the program).

Is there a way to prevent this? Or is this a non issue? I'm guessing theres no real set order to how many lines are run before it goes to the next thread, and so on.


So whats the best practice to handle this situation? I hope I'm making sense.

kirants
January 28th, 2008, 11:16 PM
It IS is problem. Please read up here:
CodeGuru: Win32 Thread Synchronization, Part I: Overview (http://www.codeguru.com/cpp/w-d/dislog/win32/article.php/c9823/)
CodeGuru: Win32 Thread Synchronization, Part 2: Helper Classes (http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c9825/)

TheCPUWizard
January 29th, 2008, 07:57 AM
Kirants links are excellent ones, but it looks like the original post may be managed code. If so, the .Net runtime provides MANY forms of thread synchronization. If it IS managed code, start looking at the "Monitor" class (nearly all sync objects either derived from or encapsulate this class.)

Red Squirrel
January 29th, 2008, 06:21 PM
Its actually stl mostly, and lot of custom stuff (its just psudo code, I just made it up). This is using pthreads. So not sure if pthreads might have something built in.

I was thinking I could just pause/unpause the threads in the spots where its crucial they don't overlap, but that is probably unefficient.

Arjay
January 29th, 2008, 09:06 PM
I was thinking I could just pause/unpause the threads in the spots where its crucial they don't overlap, but that is probably unefficient.The problem with pausing the threads is you need to be able to wake them up and you can't do that from inside the thread. What you need is to synchronize the access. On Windows you would use a critical section or mutex. I believe a mutex is available on Linux (but I'm not a Lunix expert).

Essentially, you need to guard access to the resource. In Windows, you would create a critical section, and then acquire (Enter) it and release (Leave) it when you've finished accessing the resource.

The modified source would look something like (in pseudo-code):

class SomeClass
{
public:
SomeClass( )
{
// Let the OS know you are about to use a cs object
InitializeCriticalSection( &m_cs );
}

~SomeClass( )
{
// Let the OS know you are finished with the cs
DeleteCriticalSection( &m_cs );
}


private:
CRITICAL_SECTION m_cs;
ArrayList m_arraylist;

Thread1()
{

while(true) // See the comment below about spinning
{
// Acquire the resource (lock it - this blocks other threads from going
// beyond their calls to EnterCriticalSection. As soon as the other
// reach EnterCriticalSection, they are put to sleep while this thread
// is in the code after this thread's call to EnterCriticalSection (and before
// this thread's call to LeaveCriticalSection).
EnterCriticalSection( &m_cs );
usleep(1);

if(arraylist.Size()<0)
continue;

DoStuff(&arraylist);

// Release the lock on the cs - allow other threads access to the resource
LeaveCriticalSection( &m_cs );
}
}

Thread2()
{

while(something)
{
EnterCriticalSection( &m_cs );

arraylist.Add(stuff);

LeaveCriticalSection( &m_cs );
}
}

Thread3()
{
while(true)
{
EnterCriticalSection( &m_cs );

RandomlyEmpty(&arraylist);

LeaveCriticalSection( &m_cs );
}
}
}

NOTE: You wouldn't actually want to just spin in each thread with the while(true) loop. Oridinarily you would be inside the while loop waiting on some event. The while loops in this code would hog all the resources.

exterminator
February 5th, 2008, 09:33 AM
With pthreads - look out for mutex i.e. pthread_mutex_t. And api's like pthread_mutex_lock()/pthread_mutex_unlock(). What Arjay is referring to as critical section is something like a scoped lock which you can build using pthread mutex and mutex locks exploiting RAII (a class basically whose constructor acquires the lock on the mutex and the destructor unlocks it - and have an additional interface to unlock() on demand). You could just be making those simple lock/unlock API calls as well.

If you are doing C++ (as you mention STL), why not use boost::threads rather than pthreads directly? boost::threads are object oriented and would be much easier to use and portable than pthreads. Think about the option if you can use boost::threads, if not (i.e. you existing code heavily uses pthreads already) it is perfectly fine to deal with pthreads. You can look at the various APIs and their documentation here - http://opengroup.org/onlinepubs/007908799/xsh/pthread.h.html

Hope it helps.