• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1210
  • Last Modified:

CCriticalSection and CMutex Diff

I'm trying to determine with *certainty* what is the difference between CCriticalSection and CMutex.

MSDN states the following:
Critical sections are used instead of mutexes (see CMutex) when speed is critical and the resource will not be used across process boundaries.

I'm reading that to mean you can use CCriticalSection if your code is not going to be accessed by multiple applications (via DLL).

My coworker is reading it to mean that the code is not going to be access by multiple instances.

class foo
{
 CCriticalSection m_CCriticalSection;
};

He thinks if you have multiple instances of foo, then you should be using CMutex instead of CCriticalSection.

Can someone give me a *good* explanation of the differences between CCriticalSection and CMutex?

Thanks
0
Axter
Asked:
Axter
  • 7
  • 5
1 Solution
 
jkrCommented:
>>I'm reading that to mean you can use CCriticalSection if your code is not going to be accessed by multiple applications
>> (via DLL).
>>My coworker is reading it to mean that the code is not going to be access by multiple instances.

You are both right. Multiple instances of one process are in fact multiple processes. A critical section will only work in the address space of a process that created it and cannot be shared with another process, but it definitely is unique and valid for the whole process. Additionally, critical sections are "unnamed" and therefore only identified by their control structures in the memory location they reside in. Mutexes (as events) can have (but do not have to have) names and can be shared across process boundaries (if they are named) by referring to their unique name. Apart from that, mutexes are kerel objects will all bells and whisatles, whereas critical sections are a 'user land' construct.

If you have a critical section that is a class member, you will indeed end up instantiating one critical section for each class instance, unless you make that a static member.
0
 
jkrCommented:
BTW, here's a nice explanation by Jeffrey Richter: http://www.microsoft.com/msj/archive/S1DA0.aspx

--------------------------------------------------------->8--------------------------------

As you should know, critical sections and mutexes behave almost identically. However, mutexes have a few advantages over critical sections: mutexes can synchronize threads across process boundaries, you can wait on a mutex by specifying a timeout value, and mutexes notify a thread when they are abandoned. This is a nice list of mutex features that critical sections don't share. Why use a critical section instead of a mutex? There is only one answer: critical sections are faster. Mutex objects are kernel objects and as such the functions that manipulate them (WaitForSingleObject and ReleaseMutex) require the transition from user mode to kernel mode. This transition is on the order of 600 CPU instructions (on x86 processors).

Critical sections are not kernel objects and the implementations of EnterCriticalSection and LeaveCriticalSection exist almost entirely in user mode so the CPU does not transition to kernel mode. Calling these functions executes approximately 9 CPU instructions (on x86 processors). For threads making repeated calls to malloc and free, the performance hit from using kernel objects (like mutexes) versus critical sections can be quite noticeable and is certainly not desirable.

To be fair, critical sections do not execute entirely in user mode. As long as a thread does not attempt to acquire the critical section while another thread owns it, EnterCriticalSection and LeaveCriticalSection execute entirely in user mode as I mentioned. However, if a thread attempts to enter the critical section while it is owned by another thread, the critical section degrades to a kernel object and the thread executes 600 CPU instructions. However, in most applications it is rare that two (or more) threads contend for a critical section simultaneously, which still makes critical sections very useful.

--------------------------------------------------------->8--------------------------------


http://msdn.microsoft.com/library/en-us/dndllpro/html/msdn_onthefly.asp ("Synchronization on the Fly") gives some deeper insight to the whole area.
0
 
AxterAuthor Commented:
I'm sorry jkr, but your description sounded too similar to the MS description, which still leaves me with uncertainty.

>>If you have a critical section that is a class member, you will indeed end up instantiating one critical section for each class instance

Let's say I have three MAIN threads within the same application, and each MAIN thread has it's own instance of foo.
If thread #1 blocks {foo.m_CCriticalSection.Lock()}, is that block only effecting thread #1 (and sub threads of #1)?
Or does it also effect main threads #2 and #3?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
AxterAuthor Commented:
Example:


UINT FileBridge::SendFileThread(LPVOID ptr)
{
  std::auto_ptr<foo> myfoo((foo*)ptr);
  myfoo->m_CCriticalSection.Lock(); //??????
}

Some code creating above thread:
AfxBeginThread(SendFileThread, new foo());//#1
AfxBeginThread(SendFileThread, new foo());//#2
AfxBeginThread(SendFileThread, new foo());//#3
0
 
jkrCommented:
If each thread has it's own instance of 'foo', you have three *different* instances of a critical section also, which are completely unrelated. You can think of them like local variables to these threads that will not interact. Just as if it was an 'int' member. The idea would be to have all instances of 'foo' sharing one critical section, but then you sort of need to pass them a reference or pointer.
0
 
AxterAuthor Commented:
My coworker thinks above code will block on the second thread untill #1 thread calls an unlock.
0
 
AxterAuthor Commented:
>>If each thread has it's own instance of 'foo', you have three *different* instances of a critical section also, which are completely unrelated.

That's what I thought.  Now I just have to convince my coworker. :-)
0
 
jkrCommented:
>> My coworker thinks above code will block on the second thread untill #1 thread calls an unlock.

No. Definitely not. Let's simplify the situation:

class foo
{
int m_n;
};

UINT FileBridge::SendFileThread(LPVOID ptr)
{
 std::auto_ptr<foo> myfoo((foo*)ptr);
 myfoo->m_n = 42;
}

AfxBeginThread(SendFileThread, new foo());//#1
AfxBeginThread(SendFileThread, new foo());//#2
AfxBeginThread(SendFileThread, new foo());//#3

Will all instance of 'foo' be affected by the assignment?
0
 
AxterAuthor Commented:
Thanks
0
 
AxterAuthor Commented:
>>Will all instance of 'foo' be affected by the assignment?

He thinks that CCriticalSection crosses multiple instances of the same object.
0
 
AxterAuthor Commented:
It's so much easier when you can find clear Documentation to prove your case one way or another.
But when you have document that leaves room for interpretation, it makes it much harder to make a final unquestionable determination.
0
 
jkrCommented:
>>He thinks that CCriticalSection crosses multiple instances of the same object.

No, how could they? That would work with mutexes, but not when they're unnamed. However

class foo
{

foo() : m_CMutex(FALSE,"FOO_MUTEX") {}

CMutex m_CMutex;
};

can do that (if we make the appropriate things 'public', though :o)

The unique name would make it possible to share them accross objects, since the constructor would call 'OpenMutex()' after 'CreateMutex()' faild with 'ERROR_ALREADY_EXISTS' (at least I hope so, did not check with the sources, though)
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now