![]() |
| | #1 |
| Registered User Join Date: Mar 2005 Location: New Zealand
Posts: 20
| Race condition: getting multiple threads to cooperate Now all these threads will be accessing a certain function at several different times, and while one thread is calling the function I want to block the other threads from executing the same code at the same time to prevent possible (nowever unlikely or uncritical) race conditions. Is there some simple method of doing this? I want the solution to be robust as I expect the program to be running for months on end without stopping. The program is intended for the win2k/xp platform and want it to complie no trouble in both VC6+ and BC5+. |
| FlyingDutchMan is offline | |
| | #2 |
| Registered User Join Date: Dec 2004
Posts: 95
| Executing the same code is fine, it's modifying shared data that you need to protect. Th fact you thought otherwise leads me to believe you need to learn a bit more about threading and synchronization before you dive into this. That said, you will likely want some locking, e.g. mutex (or in Windows-speak CRITICAL_SECTION). wa gotta run. |
| azteched is offline | |
| | #3 |
| Registered User Join Date: Mar 2005 Location: New Zealand
Posts: 20
| The problem is not so much locking shared data, but more to the point the serial port. I don't wont one thread coming along and interrupting another whilest its communicating on it. I would have though the easiest way to prevent problems is to block one thread from running that particular code/function that accesses the port while another thread is running it. Maybe I'm just missing something? I can see a way of doing by using a bogus object that a thread locks then it enters the function, and can be used to block other threads execution of the function until it is unlocked at the end of the function- but it doesn't seem like a very elegant solution. |
| FlyingDutchMan is offline | |
| | #4 |
| Registered User Join Date: Dec 2004 Location: Brazil, Porto Alegre
Posts: 152
| You could use semaphores. Donīt know how they work in Windows. |
| Mortissus is offline | |
| | #5 |
| Registered User Join Date: Mar 2005 Location: New Zealand
Posts: 20
| Ahh it seems that I can use InitialiseCriticalSection(), EnterCriticalSection(), LeaveCriticalSection() and DeleteCriticalSection(). This seems to be aimed at threads of the same process as opposed to mutex which is between threads on different processes. To be able for all the threads to access the threadBlocker it seems I must make it global, or either create a new object in which to encapsulate everything that get passed to the new threads. Or is it possible to pass more than one object to a new thread? I think this is about what I need to do (a brief overview of my program): Code: CRITICAL_SECTION threadBlocker;
int main()
{
InitializeCriticalSection((LPCRITICAL_SECTION) threadBlocker);
InitialiseEveryThing();
CreateThread(start master server thread);
while(some global condition) {
sleep(...);
if(some condition)
actAsClientAndDoStuff();
}
DeleteCriticalSection((LPCRITICAL_SECTION) threadBlocker);
killEveryThingElse();
return 0;
}
DWORD masterServerThread(...)
{
As required {
CreateThread(server listener thread);
}
}
DWORD listenerServerThread(...)
{
validateUserEtc();
while(some cond) {
getRemoteCommand();
serialCommand();
}
closeConnection();
}
void serialCommand(...)
{
EnterCriticalSection(threadBlocker);
serialCommunicae{}
LeaveCriticalSection(threadBlocker);
}
Last edited by FlyingDutchMan; 03-30-2005 at 09:38 AM. |
| FlyingDutchMan is offline | |
| | #6 | ||
| Registered User Join Date: Dec 2004
Posts: 95
| Quote:
Quote:
Code: struct thread_stuff {
char *something;
int something_else;
CRITICAL_SECTION* thread_lock;
};
Scoped RAII locking also helps, especially when you have multiple return paths from a function where you locked your mutex. Also: Your "while some cond" loops should probably be turned into condition variable waits. Presumably you're setting your "some cond" from one thread and then testing from another to see if there's work available, or whatever - you should probably use a condition variable & mutex to wait on the condition, rather than using sleep. Side note: boost provides an OO mutex, condition variable, and scoped RAII lock. | ||
| azteched is offline | |
| | #7 | |
| Registered User Join Date: Mar 2005 Location: New Zealand
Posts: 20
| Thanks for that. Good to know I wasn't going to far off track. The sleep is so it can update itself every 5 mins or so (connect to other computers with the same setup). According the borland C help I have here it suspends the threads execution until the time is up. The intended method of exiting the program is through a network connection so the global is there just waiting for that. I'll probably stick that global in the object that gets passed to the threads so that its no longer global (I hate globals!). You are right though - there will be an unseemly wait of upto 5 mins before exiting the main loop. I will have to get that one tieded up. The masterServerThread uses the listen() so that doesn't use anything until a connection comes in. The listenServerThread loop is waiting on data from the network so that should also be a non resource hogging wait, and the threads survival would be lucky to exceed 1 or 2 seconds (hence the unlikelyhood of race condidtions). Quote:
| |
| FlyingDutchMan is offline | |
| | #8 |
| It's full of stars Join Date: Aug 2001
Posts: 4,833
| A critical section and a mutex are different objects on a Windows system. A critical section can only used by the threads of a single process. It is very fast and has a low overhead. A named mutex can be used across process boundaries to synchronise threads in several different programs. I have a very basic MT tutorial starting here but you've got the general idea now anyway.
__________________ Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream. |
| adrianxw is offline | |
| | #9 | |
| Registered User Join Date: Dec 2004
Posts: 95
| Quote:
Even if you don't use exceptions, in general it's a good idea to use things like scoped locks if you have them available, because it makes your code easier to maintain - if you add an extra return path and forget to call LeaveCrit, then you're in trouble. My point about condition variables was more about keeping a) access to the shared variable thread-safe, and b) ensuring proper visibility of updates to it. E.g. if you do something like Code: int working = 0; //assume int assignment is atomic on your platform
int main ( ) {
beginthread ( ... );
while (working) { sleep ( ); }
printresults ( .... );
}
void* threadfunc (void*) {
// .. do stuff ..
working = 1;
}
Using a mutex (CS), or one of the Interlocked*** family of instructions should ensure proper visibilty. You should use them anyway in this situation, because "int" may not always be atomically modifiable on your platform. Anyway I'm rambling. Generally you'll be fine as long as you protect shared resources appropriately (that inclues variables, devices, etc).. | |
| azteched is offline | |
| | #10 | |
| Registered User Join Date: Mar 2005 Location: New Zealand
Posts: 20
| Quote:
| |
| FlyingDutchMan is offline | |
| | #11 |
| Registered User Join Date: Mar 2003
Posts: 3,844
| |
| Codeplug is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Need help with multiple threads | Cogman | Windows Programming | 2 | 07-05-2009 09:40 AM |
| Multiple Threads, One listener. | PING | Networking/Device Communication | 3 | 03-27-2009 12:19 PM |
| Multiple Threads | NuNn | C Programming | 3 | 03-14-2009 11:29 PM |
| Race condition | Roaring_Tiger | C Programming | 5 | 10-24-2004 09:42 PM |
| Modeless Dialogs in Multiple threads | MrGrieves | Windows Programming | 0 | 06-22-2004 01:33 PM |