Coordinating threads Part I


The most complex task when developing multithreaded application is to coordinate threads and make them work together.
When writing the thread executable code, you must consider the behavior of other threads that may be executing simultaneously, including the main VCL thread. Thread executable code can be interrupted at any time. Each thread code runs simultaneously.
In particular, you should avoid two threads trying to use the same global object or variable at the same time.
Note that local variables are always thread-safe, because each thread has its own stack memory.

Avoiding simultaneous access

To avoid clashing with other threads when accessing global objects or variables, you may need to block the execution of other threads until your thread code has finished an operation. Be careful not to block other execution threads unnecessarily. Too many locks can cause performance to degrade seriously and negate most of the advantages of using multiple threads. Improper usage of locking objects and / or critical sections can cause deadlock.

Locking objects

Some objects have built-in locking that prevents the execution of other threads from using that object instance.
For example, canvas objects (TCanvas and descendants) have a Lock method that prevents other threads from accessing the canvas until the Unlock method is called.
The VCL also includes a thread-safe list object, TThreadList. Calling TThreadList.LockList returns the list object while also blocking other execution threads from using the list until the UnlockList method is called. Calls to TCanvas.Lock or TThreadList.LockList can be safely nested. The lock is not released until the last locking call is matched with a corresponding unlock call in the same thread.
Note: Lock/Unlock methods itself use critical sections or other synchronization mechanism but there is no any "compiler magic".

Using critical sections

If objects do not provide built-in locking, you can use a critical section. Critical sections work like gates that allow only a single thread to enter at a time. To use a critical section, create a global instance of TCriticalSection. TCriticalSection has two methods, Acquire(which blocks other threads from executing the section) and Release(which removes the block).
Each critical section is associated with the global memory you want to protect. Every thread that accesses that global memory should first use the Acquire method to ensure that no other thread is using it. When finished, threads call the Release method so that other threads can access the global memory by calling Acquire.

Warning:
Critical sections only work if every thread uses them to access the associated global memory. Threads that ignore the critical section and access the global memory without calling Acquire can introduce problems of simultaneous access.

For example, consider an application that has a global critical section variable, LockXY, that blocks access to global variables

The copyright of the article Coordinating threads Part I in Delphi Programming is owned by Lyapin Ilya. Permission to republish Coordinating threads Part I in print or online must be granted by the author in writing.

Go To Page: 1 2

Articles in this Topic    Discussions in this Topic