Archived

This topic is now archived and is closed to further replies.

hellfire

Thread and CriticalSections

Recommended Posts

I am useing the _beginthread function to create two threads. They both access the same object, but there is only one varible which is an int, that I want to make a critical section. What is the best and fastest way to to this?

Share this post


Link to post
Share on other sites
It really depends on your intended purpose. You could use semaphores, mutexes, a monitor...if it''s an extremely simple case - where you''re trying to synchronize 2 threads, I''d suggest having a bolt variable.

critical section:

// ** bolt is a global boolean, which is seen by both threads
if( bolt )
{
bolt = false;
// ** do your work
bolt = true;
}

If you want more complicated, such as suspending a thread if it can''t enter the section, you should look into the operating system''s synchrnization functions and employ them. Given so little about your problem, that''s all I can suggest. G''luck!

Share this post


Link to post
Share on other sites
If you''re running on Windows use _beginthreadex instead of _beginthread. Only use _beginthread if your thread function uses the _cdecl calling convention - and if it does consider reworking it to use _stdcall instead.

For details see:
http://support.microsoft.com/default.aspx?scid=KB;EN-US;q132078&
http://www.microsoft.com/msj/0799/win32/win320799.htm
http://www.microsoft.com/msj/1099/win32/win321099.htm

Share this post


Link to post
Share on other sites
Under Win32, a CriticalSection and a Mutex are very similar.
The only difference was that a Mutex can be given a name so that different processes can use it. Unless you need to synchronize across process boundaries, use a CriticalSection, which is faster.

Share this post


Link to post
Share on other sites
for simple thread safety, I use these 2 classes:


  
// file: lockobj.h

#include <windows.h>

class CritSec : public CRITICAL_SECTION
{
public:
CritSec() { ::InitializeCriticalSection(this); }
~CritSec() { ::DeleteCriticalSection(this); }
};

class Lock
{
public:
Lock(CRITICAL_SECTION& cs) : m_cs(&cs) { ::EnterCriticalSection(m_cs); }
~Lock() { ::LeaveCriticalSection(m_cs); }
private:
CRITICAL_SECTION* m_cs;
};



to use:


  
void do_something()
{
Lock l(g_cs); // g_cs is an instance of CritSec

// potentially thread-unsafe code here

}

Share this post


Link to post
Share on other sites
quote:
Original post by siaspete
If you want to protect variables you''re probably better using a mutex. A critical section is to prevent the same bit of code being run in several threads concurrently.


Uh.

Critical sections are for protecting variables too. The difference is that CSes are strictly per-process (and have a rather limited API; you can ininitalize, enter, leave, uninitialize them, and I think that''s all) whereas mutexes can be shared between processes and have the full set of WaitXxx() calls available.

Unless you need the extra functionality a mutex provides, a CS is a better choice, as they''re somewhat faster.

Share this post


Link to post
Share on other sites
quote:
Original post by DrPizza
Unless you need the extra functionality a mutex provides, a CS is a better choice, as they're somewhat faster.


Not only "somewhat"

Grabbing a CS (~10 CPU instructions on x86) is much faster than a mutex, assuming only one thread tries to acquire the lock (there is no "contention"), because then the CS will operate entirely in usermode. EDIT: Using a mutex for locking always forces a transition to kernelmode.
If there is another thread waiting for the CS a transition to kernelmode is needed and the penalty for that is HIGH (~500 CPU instructions on x86). The kernelmode transition can luckily normally be avoided by using spinlocks and TryEnterCriticalSection().


quote:
Original post by siaspete
If you want to protect variables you're probably better using a mutex. A critical section is to prevent the same bit of code being run in several threads concurrently.

You're right about CS, but the context gets incorrect.
There is no such thing as protecting a variable. You protect code. If you need to protect a variable this is done by protecting all accesses to the variable. Mutex and CS are two ways of doing that. A CS gives better performance, while the Mutext has other advantages such as working cross-process.
EDIT: I missed that DrPizza already had commented this, sorry about that.

A good article is: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndllpro/html/msdn_locktest.asp

[edited by - developer on August 15, 2002 6:40:08 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Bashar
// ** bolt is a global boolean, which is seen by both threads
if( bolt )
{
bolt = false;
// ** do your work
bolt = true;
}


This is NOT guaranteed to function correctly - the bolt variable constitutes a RMW sequence and needs synchronization itself to be multi-thread safe.
After the ''if(bolt)'' check the CPU may be swapped to the other thread which may execute the same line (both will succeed), and both will be executing code inside the critical section.

(P.S. SpinLock''s are only useful on multi-processor machines - they just waste CPU time on single systems)

In computer science terms, the code between the mutex locking/unlocking is called a critical section. In Win32 terms, a critical section is a process specific mutex.

Share this post


Link to post
Share on other sites