gpt4 book ai didi

multithreading - Delphi:使用关键部分的首选保护方式

转载 作者:行者123 更新时间:2023-12-03 14:45:47 25 4
gpt4 key购买 nike

我有一个对象 x 需要从多个(5 个以上线程)访问。对象的结构为

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

更好(最优雅)的保护方式是什么:

一)

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;

结束;

并且始终以 GetSafeObj().x:= 3; 的形式访问对象

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;

结束;

并始终正常访问该对象。我想第一个选项更优雅,即使两种方法都可以正常工作。有评论吗?

最佳答案

选择选项 B,使临界区位于对象内部。如果类的用户必须使用外部函数来安全地访问实例,那么不可避免地会有人不这样做,房子就会折叠。

您还需要考虑您想要保护哪些操作语义免受多个并发读取和写入的影响。如果在 getter 和 setter 中放置锁,则可以保证对象内部一致,但对象的用户可能会看到多线程工件。例如,如果线程 A 将 10 写入对象的属性,而线程 B 将 50 写入同一对象的该属性,则只有其中一个可以是最后一个。如果 A 碰巧先写入,那么 A 将观察到他们向该属性写入了 10,但是当他们再次读回时,他们看到 B 的 50 潜入了 A 的读后写之间的间隙。

另请注意,您实际上并不需要锁来保护单个整数字段。如今,对齐指针大小的整数写入几乎在每个硬件系统上都是原子操作。您肯定需要一个锁来保护多部分数据(例如结构)或多步骤操作(例如同时更改两个相关字段)。

如果有任何方法可以重新设计您的设计,使这些对象成为线程上特定操作的本地对象,那就去做吧。制作数据的本地副本可能会稍微增加您的内存占用量,但它可以极大地简化您的多线程代码,并且比在应用程序中留下互斥地雷的运行速度更快。还要寻找其他简化的假设 - 如果您可以设置系统,使对象在可用于多个线程的同时是不可变的,那么该对象根本不需要任何锁保护。只读数据有利于跨线程共享。非常非常好。

关于multithreading - Delphi:使用关键部分的首选保护方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8101711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com