Different multi-threading problems

In the last few articles we saw how to use the synchronization classes. In this article we would discuss when to use these classes. We would also see how to use synchronization access classes like CSingleLock and CMultiLock.

To determine which synchronization class we should use follow the rules given below:

  • If the application has to wait for something to happen before it can access the resource (for example, a linked list must be populated before sorting the list or data must be received from a communications port before it can be written to a file) use CEvent.
  • If more than one thread within the same application accesses the resource at one time (for example, your application allows up to five windows with views on the same document) use CSemaphore.
  • If more than one application use the resource (for example, the resource is in a DLL) use CMutex, otherwise use CCriticalSection.

Using Synchronization Access Classes: CSingleLock and CMultiLock

In the programs that we wrote in the past few weeks we used Lock( ) and Unlock( ) member functions of the synchronization classes like CCrticalSection, CMutex, CEvent, etc. to control the access of a resource by multiple threads. We can also use synchronization access classes i.e. CSingleLock and CMultiLock for this purpose. These classes have their own Lock( ) and UnLock( ) functions. If the application is concerned with accessing a single controlled resource only, use CSingleLock. If it needs access to any one of a number of controlled resources, use CMultiLock.

Terminating threads

We can terminate a thread in two ways. The straightforward way is to simply return from the thread function. Alternatively, the thread can call a function AfxEndThread( ). This function terminates the calling thread. If we want to terminate the thread from another thread, Microsoft documentation recommends that the thread should signal the other thread to terminate itself.

Managing threads

An application having multiple threads can suspend execution of threads temporarily and resume it again. AfxBeginThread( ) function returns a pointer to a CWinThread object. Using this pointer we can call CWinThread::SuspendThread( ) function to suspend the thread temporarily. Calling CWinThread::ResumeThread( ) function resumes the execution again.

MFC Limitations

Threads generally share global or dynamically allocated variables and objects. However, there are some limitations in the sharing of MFC objects:

  • Two threads shouldn’t attempt to access the same MFC object simultaneously. For example, two threads can share a single CString object, provided they don’t attempt to manipulate the object-by calling a CString member function at the same time. To prevent separate threads from simultaneously accessing an MFC object, we can use any of the synchronization methods.
  • An object of any of the following MFC classes should be accessed only by the thread that created the object:

CWnd

CDC

CMenu

CGdiObject

All these classes store a Windows handle. For example, a CWnd object stores a handle to a window which is kept in the object’s m_hWnd data member. If a given thread has created an object of one of these classes, but we want to access the underlying item from a second thread, we should pass the second thread the Windows handle, and the second thread should create its own object.

Synchronization Overview

There exist four mechanisms for limiting access to common resources and synchronizing processing between threads. All these mechanisms work in different ways and suitability of each depends on the circumstances. The four mechanisms are:

Critical Sections

A critical section is a mechanism that limits access to a certain resource to a single thread within an application. A thread enters the critical section before it needs to work with the specific shared resource and then exits the critical section after it has finished accessing the resource. If another thread tries to enter the critical section before the first thread exits the critical section, the second thread is blocked and does not take any processor time until the first thread exits the critical section, allowing the second to enter. You use critical sections to mark sections of code that only one thread should execute at a time. This doesn’t prevent the processor from switching from one thread to another; it just prevents two or more threads from entering the same section of code.

Mutexes

Because of their availability across the operating system, mutexes carry much more overhead than critical sections do. A mutex lifetime does not end when the application that created it shuts down. The mutex might still be in use by other applications, so the operating system must track which applications are using a mutex and then destroy the mutex once it is no longer needed. In contrast, critical sections have little overhead because they do not exist outside the application that creates and uses them. After the application ends, the critical section is gone.

Semaphores

You use semaphores with resources that are not limited to a single thread at a time—a resource that should be limited to a fixed number of threads. A semaphore is a form of counter, and threads can increment or decrement it. The trick to semaphores is that they cannot go any lower than zero. Therefore, if a thread is trying to decrement a semaphore that is at zero, that thread is blocked until another thread increments the semaphore.

Events

More the threads running at one time, the slower each of those threads performs its tasks. Therefore, if a thread does not have anything to do, block it and let it sit idle, allowing other threads to use more processor time and thus run faster until the conditions are met that provide the idle thread with something to do. Thread synchronization events do not use the normal event queuing and handling mechanisms. Instead of being assigned a number and then waiting for that number to be passed through the Windows event handler, thread synchronization events are actual objects held in memory. Each thread that needs to wait for an event tells the event that it is waiting for it to be and then goes to sleep. When the event is triggered, it sends wake-up calls to every thread that told it that it was waiting to be triggered. The threads pick up their processing at the exact point where they each told the event that they were waiting for it

It's very calm over here, why not leave a comment?

Leave a Reply




Categories

UserOnline

Improve the web with Nofollow Reciprocity.

Powered by Yahoo! Answers