![]() |
| | #1 |
| * Death to Visual Basic * Join Date: Aug 2001
Posts: 768
| CreateThread ?! 1.) Can I use the same created semaphore for of the threads running at the same time? Code: CreateSemaphore(NULL, 4, 4, THREAD_SEMAPHORE); Code: HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes DWORD dwStackSize, // initial thread stack size LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function LPVOID lpParameter, // argument for new thread DWORD dwCreationFlags, // creation flags LPDWORD lpThreadId // pointer to receive thread ID ); Thank you.
__________________ "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe http://www.Bloodware.net - Developing free software for the community. |
| Devil Panther is offline | |
| | #2 |
| Unregistered User Join Date: Sep 2005 Location: Antarctica
Posts: 341
| it doesn't matter what you give to lpThreadId as long as it's a valid pointer and you don't care to use the data it returns. What are you using hte semaphore for? If you want to use it to synchronize the threads then you will have to use the same for all them. I usually use CriticalSections for synchronizing, but with a semaphore you can specify how many threads are able to access the same code at the same time, I've never had a reason to let more than one thread access a critical section at the same time though. |
| rockytriton is offline | |
| | #3 |
| Disrupting the universe Join Date: Jun 2005
Posts: 243
| The lpThreadId parameter of the CreateThread function should always be used for backwards compatability (MSDN: "Windows Me/98/95: This parameter may not be NULL") with older Windows systems. You do not nessecarily have to use it, it just has to be a pointer to a DWORD, normally though, I always give some kind of message in my diagnostics programs stating the thread ID to make my code more opaque during runtime. As for the semaphore question: you should REALLY question using Semaphores, Mutexes or Events in comparison with something like the Interlocked functions or Critical Sections. Mutexes and Semaphores are what a big windows programmer would call 'kernel objects.' Kernel objects exist as far as the kernel is considered, and they're called kernel objects because the kernel synchronizes access to them using kernel synchronization functions (namely, the WaitFor[Single|Multiple]Object[s](...) function and the Release*(...) functions). The astute reader would realize that naturally for the kernel to schedule such things it would take more CPU time, therefore, you should use them when you need them. Impractical use of kernel object synchronization between threads Using them to access a simple global variable. Example: Code: MYTYPE g_x;
HANDLE g_hMutex;
//...
void funcinator1() {
-- WaitForSingleObject(g_hMutex,INFINATE);
//Computate on g_x;
-- ReleaseMutex(g_hMutex);
}
void funcinator2() {
-- WaitForSingleObject(g_hMutex,INFINATE);
//Computate on g_x;
-- ReleaseMutex(g_hMutex);
}
int WINAPI WinMain(...) {
-- g_hMutex = CreateMutex(NULL,FALSE,NULL);
-- HANDLE hThread1 = CreateThread(...,(LPTHREAD_START_ROUTINE)funcinator1,...);
-- //...
-- HANDLE hThread1 = CreateThread(...,(LPTHREAD_START_ROUTINE)funcinator2,...);
-- //...
}
Correct usage of kernel objects Using them to wait for something like a thread to return. Example: Code:
void funcinator() {
-- //...
}
int WINAPI WinMain(...) {
-- HANDLE hThread = CreateThread(...,(LPTHREAD_START_ROUTINE)funcinator,...);
-- WaitForSingleObject(hThread,INFINATE);
}
A semaphore would be useful in this canonical situation: writing a webserver. You could have it so that a call to CreateSemaphore lets 3 threads through and has them handle requests. So on a clients' request, one thread would be created and it would wait for a semaphore and if it is open it will be let through to process the clients request. But if 3 clients are already being handled, if a fourth client connects the thread will be created, but it will have to wait for another thread to let go of it's semaphore object and decrease it's lock count (and logically, when a semaphore is 'grabbed it's lock count increases.) Mutexes apply the same way. They (like Semaphores) ensure that a thread has exclusive access to a resource (contra semaphores in which x amount of threads can access one resource.) But like said earlier, why would you need a mutex if a critical section already exists because they have very similar semantics? Well, for one, you can wait on a mutex object for x milliseconds before giving up, while with a critical section you have to wait, so you could have an application wait for an object for 100 milliseconds in a loop, and when that expires process it's messages then continuing in that loop (of course, you can have a thread wait for a critical section and continue immediately if it's not available, but that's not the point.) Second, mutexes are cross-process objects. I can use CreateRemoteThread to create a thread in a remote process, but I'll still have the ability to use WaitForSingleObject on it because the HANDLE returned is associated with that kernel object. Again, question the use of semaphores, they're extremely slow compared to something like a Critical section, but if you need x amount of threads to run something while the others wait, then you should use a Semaphore. EDIT: A side note on threading: don't do it unless it's not possible any other way, I might be stating the obvious, but seriously, exhaust every resource (pun not intended) you have before having to resorting to threads. You easily tack on weeks of debugging and auditing for the addition of even a single thread. If you have to, use fibers. Fibers are like 'miniature' threads within threads. A process has threads, and threads have fibers. Ergo: Process | +--Thread1 | +Fiber1 +Fiber2 +Fiber3 +Fiber4 +--Thread2 [No fibers] Fibers are practically like threads, only you define your OWN scheduling algorithm, because the kernel synchronizes threads, but fibers don't exist as far as the kernel is concerned. Their context switches are also much less expensive than a Threads' is, the only thing is be very hesitent about mixing threads with fibers. Because if in the above example, Fiber 1 of thread 1 calls WaitForSingleObject on a resource that Thread2 at that point in time owns,Thread1 hault's, and so do all of it's fibers. This is because WaitForSingleObject has what we call Thread Affinity meaning it pauses the thread, and if you use fibers, fibers compose the thread itself (actually when you call ConvertThreadToFiber I guess you could say the thread doesn't exist anymore, more like a 'psuedo thread,' and it exists so the kernel knows where to return so the fibers can then take over via the internal scheduler, because, again, the kernel doesn't know fibers exist and therefore can't return to one of them.) Fibers also don't need any resource synchronization between fibers because the resource will always be owned by the Thread. You use fibers by calling ConvertThreadToFiber, then calling CreateFiber and finally switching between fibers via the SwitchToFiber function.
__________________ operating systems: mac os 10.6, debian 5.0, windows 7 editor: back to emacs because it's more awesomer!! version control: git website: http://www.nijoruj.org/~as/ Last edited by Mad_guy; 11-05-2005 at 11:40 PM. |
| Mad_guy is offline | |
| | #4 |
| * Death to Visual Basic * Join Date: Aug 2001
Posts: 768
| I'm still trying to learn about working with Threads, and one day I hope to understand them the way you do, but at the moment I wish to know; Can I create a single semaphore when I attempt to run x threads side by side while they need to access the same global variables?
__________________ "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe http://www.Bloodware.net - Developing free software for the community. |
| Devil Panther is offline | |
| | #5 |
| Unregistered User Join Date: Sep 2005 Location: Antarctica
Posts: 341
| Yes you can, but like he said, you probably don't want a semaphore. What I would suggest to do is to create a CRITICAL_SECTION. So, globally, you declare your critical section and your global data that you want to share: Code: CRITICAL_SECTION lock; int my_counter; Code: int WinMain(...)
{
InitializeCriticalSection(&lock);
}
Code: DWORD WINAPI MyThread1(LPVOID p)
{
EnterCriticalSection(&lock);
my_counter++;
LeaveCriticalSection(&lock);
...
EnterCriticalSection(&lock);
my_counter--;
LeaveCriticalSection(&lock);
}
Code: DWORD WINAPI MyThread2(LPVOID p)
{
EnterCriticalSection(&lock);
my_counter++;
LeaveCriticalSection(&lock);
...
EnterCriticalSection(&lock);
my_counter--;
LeaveCriticalSection(&lock);
}
Last edited by rockytriton; 11-08-2005 at 05:32 PM. |
| rockytriton is offline | |
| | #6 |
| * Death to Visual Basic * Join Date: Aug 2001
Posts: 768
| Can you please explain alittle more about the critical section, because I don't really understand how does it stop me from using my_counter more than once at the same time? It's not like it's bind in some way to lock, no?
__________________ "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe http://www.Bloodware.net - Developing free software for the community. |
| Devil Panther is offline | |
| | #7 |
| Unregistered User Join Date: Sep 2005 Location: Antarctica
Posts: 341
| when you call EnterCriticalSection and then another thread calls EnterCriticalSection with the same CRITICAL_SECTION pointer, the second thread will wait before exiting the function until the first thread calls LeaveCriticalSection to "unlock" the pointer so that it can be locked again. The best way to understand it is to create a little program that uses it, create two threads, have them both enter the critical section, print a line, sleep for 10 seconds, then print another line and leave the critical section, you will see that the second thread to enter will not print any output until the first one has finished and left the critical section. Last edited by rockytriton; 11-11-2005 at 10:22 AM. |
| rockytriton is offline | |
| | #8 |
| * Death to Visual Basic * Join Date: Aug 2001
Posts: 768
| So in other words, I don't need any semaphore, should I really use threads without a semaphore that will allow them to share variables?
__________________ "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe http://www.Bloodware.net - Developing free software for the community. |
| Devil Panther is offline | |
| | #9 |
| Unregistered User Join Date: Sep 2005 Location: Antarctica
Posts: 341
| it's not that these thread synchronization techniques "allow" threads to share data, it's that they provide a way to ensure that threads who share data do not corrupt the data by modifying it concurrently. |
| rockytriton is offline | |
| | #10 |
| * Death to Visual Basic * Join Date: Aug 2001
Posts: 768
| Ok, I'm alittle confused at the moment... Let me see if I got this right; A semaphore is used to control the number of threads to access the same resources at the same time (a thread count limitation). While EnterCriticalSection is for control over critical code, to forbid different threads that share the same semaphore to access the same shared resources at the same time. So what is the right way to work with multiple threads running at the same time and accessing the same global variables? Should I continue using a semaphore, but also add EnterCriticalSection to my code? Is there any better way, except using fibers?
__________________ "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe http://www.Bloodware.net - Developing free software for the community. |
| Devil Panther is offline | |
| | #11 |
| Unregistered User Join Date: Sep 2005 Location: Antarctica
Posts: 341
| do you want more than one thread to modify the data at the same time? If so, use a semaphore, if you no more than one thread to modify the shared data at the same time, then use a critical section, now if you want no more than one process to modify the shared data at the same time (such as a file), use a mutex. |
| rockytriton is offline | |
| | #12 |
| * Death to Visual Basic * Join Date: Aug 2001
Posts: 768
| So I shouldn't mix between a Ctritical Section and a Semaphore?
__________________ "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe http://www.Bloodware.net - Developing free software for the community. |
| Devil Panther is offline | |
| | #13 |
| Unregistered User Join Date: Sep 2005 Location: Antarctica
Posts: 341
| no, they aren't the same, a semaphore lets you have more than one thread access the data if you wish, but you can limit it to one as well I believe, I've never used them, only read about them. I've always used either critical sections or mutexes. |
| rockytriton is offline | |
| | #14 |
| * Death to Visual Basic * Join Date: Aug 2001
Posts: 768
| it's not really what i'm asking, what I what to know is, should I use semaphores to limit the number of threads to access the same data and also use Critical Section to avoid mistakes?
__________________ "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe http://www.Bloodware.net - Developing free software for the community. |
| Devil Panther is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| CreateThread() function question | chiefmonkey | C++ Programming | 5 | 05-15-2009 07:52 AM |
| compiler doesn't like CreateThread | finkus | C++ Programming | 6 | 11-30-2005 03:06 AM |
| sending arguments to function using CreateThread | Micko | C++ Programming | 3 | 07-15-2004 07:07 PM |
| CreateThread and lpParam | Hunter2 | Windows Programming | 6 | 06-02-2004 04:46 PM |
| pass several arguments to LPVOID param of CreateThread | Echidna | Windows Programming | 4 | 05-05-2002 10:18 AM |