Shared data with built-in locking

Sometimes you don't need to implement an additional locking mechanism because Delphi already does that for you. The runtime library contains three such data structures—TThreadList, TThreadList<T>, and TThreadedQueue<T>. The first one can be found in the System.Classes unit, while the other two live in System.Generics.Collections.

Both variants of TThreadList work the same. They don't expose the normal list-management functions (such as Add, Remove, Items[], and so on). Instead of that, they implement the LockList function, which uses TMonitor to acquire access to an internal TList (or TList<T>) object and returns that object. To release access to this list, the program has to call the UnlockList function.

The following example from the SharedList demo shows how to use TThreadList<Integer> to represent the shared storage. To access the shared list, the code calls FThreadList.LockList. This function returns a TList<Integer> object, which can be then used in the code. To release the shared list, the code calls FThreadList.UnlockList:

procedure TfrmSharedList.ThreadListReader;
var
i, j, a: Integer;
list: TList<Integer>;
begin
for i := 1 to CNumReads do
begin
list := FThreadList.LockList;
for j := 0 to FList.Count - 1 do
a := FList[j];
FThreadList.UnlockList;
end;
end;
Using the list returned from the LockList after UnlockList was called is a programming error that cannot be caught by the compiler. Be careful!

Comparing the various approaches in the SharedList demo gives interesting results. As expected, the critical section-based locking is the slowest. More interestingly, the TMonitor locking used in the TThreadList is faster than the TMREWSync implementation. The following screenshot shows a comparison of execution times measured on the test computer:

I've said it before and I'll say it again—Delphi's multiple readers, exclusive writer implementation is really not very fast. You should always compare it to a normal locking, implemented with either a TMonitor or a TSpinLock.

The third data structure, TThreadedQueue<T>, implements a standard first in, first out fixed-size queue. All operations on the queue are protected with a TMonitor. I will use this data structure in practical examples near the end of this chapter and all through Chapter 6, Working with Parallel Tools.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.88.73