Delphi: Preferred Security Method Using Critical Partitions

I have an x ​​object that needs to be accessed from several (5+ threads). Object structure

Tx = class private Fx: integer; public property x: integer read Fx read Fx; etc; 

What is the best (most elegant) way to protect:

but)

 Tx = class private Fx: integer; public property x: integer read Fx read Fx; public constructor Create; <--- Create the criticalsection here destructor Destroy; <--destroy it here etc; var cs: TCriticalSection; Obj: Tx; function GetSafeObject(): Tx; begin CS.Enter; try Result:= Obj; finally CS.Leave; 

end;

and always refer to the object as GetSafeObj (). x: = 3;

or

 Tx = class private Fx: integer; FCS: TCriticalSection; public property x: integer read GerX read SetX; public constructor Create; <--- Create the criticalsection here destructor Destroy; <--destroy it here etc; where function Tx.Getx(): integer; begin CS.Enter; try Result:= Fx; finally CS.Leave; end; end; 

end;

and always refer to the object normally. I guess the first option is more elegant, even if both methods should work fine. Ay comments?

+8
multithreading delphi
source share
3 answers

Go to option B, making the critical section internal to the object. If a class user must use an external function to securely access the instance, it is inevitable that someone will not and the house will collapse.

You also need to think about what operational semantics you want to protect against multiple simultaneous reads and writes. If you put a lock in your receiver and setter, you can guarantee that your object is internally consistent, but users of your object can see multi-threaded artifacts. For example, if thread A writes 10 to a property of your object, and thread B writes 50 to this property of the same object, only one of them may be the last. If A happens first, then A will observe that they wrote 10 to the property, but when they read it again, they saw that B 50 breaks in there between A-read-after-write.

Note that you really don't need a lock to protect an entire whole field. Dedicated integer entries with a fixed pointer represent atomic operations for almost every hardware system today. You definitely need a lock to protect multicomponent data, such as structures or multi-step operations, such as changing two related fields at the same time.

If you can somehow redesign your project to make these objects local to a specific operation in the stream, do it. Creating local copies of the data can slightly increase the amount of memory, but it can greatly simplify your code for multithreading and work faster than leaving ground mutex mines throughout the application. Look for other simplifying assumptions: if you can configure your system so that the object remains unchanged as long as it is available for several threads, then the object does not need any security locks at all. Read-only data is useful for sharing streams. Very well.

+7
source share

Bringing CS to an object object and using CS inside getter / setter methods of properties is the right approach. The other approach does not work, because it locks and unlocks the CS before the object actually runs, so the value of the property is not protected at all.

+6
source share

An easy way is to create a thread-safe wrapper around an object similar to a TThreadList . The shell needs two methods: Lock (to enter the critical section and return the internal object) and Unlock (to exit the critical section).

+5
source share

All Articles