Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 单向delphi线程通信?_Multithreading_Delphi_Variables - Fatal编程技术网

Multithreading 单向delphi线程通信?

Multithreading 单向delphi线程通信?,multithreading,delphi,variables,Multithreading,Delphi,Variables,假设我的Delphi程序有两个线程 当然是主线程和运行线程(始终运行,永不停止) 我想知道在运行线程中更新变量(16个原子整数)而不产生问题的最佳方法是什么 runner线程由始终通过USB发送低级数据组成(时间关键如果您考虑公开运行线程的某些变量,然后使用主线程更改这些变量,请不要!我是认真的。不要 为什么不呢?因为您的主线程永远不知道何时更改这些变量是安全的,并且最终可能会在运行线程读取这些变量的同时更改它们 因此,我将创建一个包含所有变量的记录,但该记录超出了您的范围 然后我会确保对该记录

假设我的Delphi程序有两个线程

当然是主线程和运行线程(始终运行,永不停止)

我想知道在运行线程中更新变量(16个原子整数)而不产生问题的最佳方法是什么


runner线程由始终通过USB发送低级数据组成(时间关键如果您考虑公开运行线程的某些变量,然后使用主线程更改这些变量,请不要!我是认真的。不要

为什么不呢?因为您的主线程永远不知道何时更改这些变量是安全的,并且最终可能会在运行线程读取这些变量的同时更改它们

因此,我将创建一个包含所有变量的记录,但该记录超出了您的范围

然后我会确保对该记录中的数据所做的所有更改都受到critical section的保护,这是为了确保只有一个线程同时访问该记录

然后在你的runner线程中,我将从该记录中读取数据,并制作一个本地副本(该副本在你的运行线程中)。现在,该记录的读取再次受到critical section的保护

现在你可能会问自己,为什么我要从正在运行的线程中读取这些变量的数据。主要原因是,你正在运行的线程现在可以更新这些变量中的数据,而不可以

我之所以将变量数据存储在记录中,是为了使关键部分的输入和输出尽可能快。
您可以看到,当您使用临界区时,输入临界区将锁定您将在临界区内访问的所有变量。因此,如果您有多个临界区,则过程可能需要一段时间,因为这些变量正在逐个锁定。但是,如果您将所有变量存储在输入临界区的记录中,则所有部分将立即锁定整个记录。

当离开关键区域,访问变量被解锁时,同样的情况也适用。

您的问题非常广泛

有许多可用选项,最适合您的选项取决于您的特定需求和环境。您需要提供有关希望主线程在运行线程上更新的数据类型的更多详细信息。预计更新的频率是多少?您已经声明运行线程是时间关键型的,这意味着您希望eeping锁(PS:多线程应用程序中速度减慢的主要原因是不同线程竞争相同的锁。称为锁争用。)最低限度。(正如我所说:这取决于您的需要。)

PS:必须使用主线程设置的所有数据吗?或者运行线程可以简单地使用最新的可用数据,而忽略可能分配的中间值吗?这个问题的答案产生了根本不同的选项


例如,可以在没有任何锁定的情况下执行原子更新。请查看
TThread.Terminated
。这是一个简单的值。更新此特定值不需要任何锁定。不存在任何问题的争用条件,因为处理器将作为整个原子单元读取或写入该值

即使您在更新
的同时没有终止
循环正在读取值,也不会有问题。更新将在读取之前发生(导致线程退出循环),或者在读取之后发生(导致在下一次读取时循环退出之前再进行一次迭代)

PS:重要的是要知道设置字符串值不是原子操作

现在,您已经指出主线程根本不需要读取运行线程的数据。但我将使用这种可能性作为对比示例。如果需要在运行线程上增加一个整数值,将需要保护。这是因为增加一个值是一个多步骤操作:

  • 读取值
  • 对读取的值执行计算
  • 写一个新值
如果运行线程与主线程同时使用该值,则可能会得到不一致的结果

另一种可能导致问题的情况是,数据由许多相互作用的值组成。例如,
NoOfUnits
MassPerUnit
组合使用,以确定
TotalMass
。单独更新这些值可能导致竞争条件导致不一致的行为

answer提供了一种保护多个值的技术。但是请注意,当前版本的answer中存在一些严重错误

注意:如果您将数据封装在一个单独的对象中,则可以在不使用任何锁的情况下更新运行线程的数据,因为您可以自动更新指针值。(VERY NB:您必须遵守一些特殊规则,并且您需要找出如何避免内存泄漏……但这是一个更具体问题的细节。)

另一个选项是将运行线程实现为消息队列。例如,当主线程想要更改值时,它会向运行线程发送一条消息。只有在“安全”的情况下,运行线程才会处理更改的值指令。(同样,此操作的可行性取决于您的特定要求。)


最后一点,除了保护数据不受比赛条件的影响外,还有一些额外的问题。跑步者线程的时间要求到底有多高?它能完成多少处理?它是否需要对某些事件做出快速响应?如果需要,是什么事件

这些问题的答案对于理解y的理想结构很重要