微波EDA网,见证研发工程师的成长!
首页 > 测试测量 > 测试测量技术文库 > LabWindows?/CVI中的多线程技术

LabWindows?/CVI中的多线程技术

时间:12-23 来源:互联网 点击:

为了使用LabWindows/CVI的异步定时器在辅助线程中运行代码,需要调用Toolslib中的NewAsyncTimer函数。需要向函数传递在辅助线程中运行的函数名称和函数执行的时间间隔。传递给NewAsyncTimer的函数被称为异步定时器回调函数。异步定时器仪器驱动程序会按照用户指定的周期调用异步定时器回调函数。异步定时器回调函数的名称是任意的,但是必须遵循下面的原型:

int CVICALLBACKFunctionName(int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2);

由于LabWindows/CVI的异步定时器仪器驱动使用Windows多媒体定时器来实现异步定时器回调函数,所以用户可指定的最小间隔是随使用的计算机不同而变化的。如果用户指定了一个比系统可用的最大分辨率还小的时间间隔,那么可能会产生不可预知的行为。不可预知的行为通常发生在设定的时间间隔小于10ms时。同时,异步定时器仪器驱动使用一个多媒体定时器线程来运行单个程序中注册的所有异步定时器回调函数。所以,如果用户希望程序并行地执行多个函数,那么NI公司推荐使用LabWindows/CVI Utility Library中的线程池函数来代替异步定时器函数。

5. 保护数据

在使用辅助线程的时候,程序员需要解决的一个非常关键的问题是数据保护。在多个线程同时进行访问时,程序需要对全局变量、静态局部变量和动态分配的变量进行保护。不这样做会导致间歇性的逻辑错误发生,而且很难发现。LabWindows/CVI提供了各种高级机制帮助用户对受到并发访问的数据进行保护。保护数据时,一个重要的考虑就是避免死锁。

如果一个变量被多个线程访问,那么它必须被保护,以确保它的值可靠。例如下面一个例子,一个多线程程序在多个线程中对全局整型counter变量的值进行累加。

count = count + 1;

这段代码按照下列CPU指令顺序执行的:

1.将变量值移入处理器的寄存器中

2.增加寄存器中的变量值

3.把寄存器中的变量值写回count变量

由于操作系统可能在线程运行过程中的任意时刻打断线程,所以执行这些指令的两个线程可能按照如下的顺序进行(假设count初始值为5):

线程1:将count变量的值移到寄存器中。(count=5,寄存器=5),然后切换到线程2(count=5,寄存器未知)。

线程2:将count变量的值移到寄存器中(count=5,寄存器=5)。

线程2: 增加寄存器中的值(count=5,寄存器=6)。

线程2: 将寄存器中的值写回count变量(count=6,寄存器=6),然后切换回线程1.(count=6,寄存器=5)。

线程1: 增加寄存器的值。(count=6,寄存器=6)。

线程1: 将寄存器中的值写回count变量(count= 6, register = 6)。

由于线程1在增加变量值并将其写回之前被打断,所以变量count的值被设为6而不是7。操作系统为系统中地每一个线程的寄存器都保存了副本。即使编写了count++这样的代码,用户还是会遇到相同的问题,因为处理器会将代码按照多条指令执行。注意,特定的时序状态导致了这个错误。这就意味着程序可能正确运行1000次,而只有一次故障。经验告诉我们,有着数据保护不当问题的多线程程序在测试的过程中通常是正确的,但是一到客户安装并运行它们时,就会发生错误。

需要保护的数据类型

只有程序中的多个线程可以访问到的数据是需要保护的。全局变量、静态局部变量和动态分配内存位于通常的内存空间中,程序中的所有线程都可以访问它们。多个线程对内存空间中存储的这些类型的数据进行并发访问时,必须加以保护。函数参数和非静态局部变量位于堆栈上。操作系统为每个线程分配独立的堆栈。因此,每个线程都拥有参数和非静态局部变量的独立副本,所以它们不需要为并发访问进行保护。下面的代码显示了必须为并发访问而保护的数据类型。

int globalArray[1000];// Must be protected
static staticGlobalArray[500];// Must be protected
int globalInt;// Must be protected

void foo (int i)// i does NOT need to be protected
{
int localInt;// Does NOT need to be protected
int localArray[1000];// Does NOT need to be protected
int *dynamicallyAllocdArray;// Must be protected
static int staticLocalArray[1000];// Must be protected

dynamicallyAllocdArray = malloc (1000 * sizeof (int));
}

如何保护数据

通常说来,在多线程程序中保存数据需要将保存数据的变量与操作系统的线程锁对象关联起来。在读取或者设定变量值的时候,需要首先调用操作系统API函数来获取操作系统的线程锁对象。在读取或设定好变量值后,需要将线程锁对象释放掉。在一个特定的时间内,操作系统

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top