C 将纳秒转换为微秒
我正在使用下面的代码将nano转换为micro-sec 这段代码主要运行罚款,但有时我看到usTick给出的值远远超过当前时间 例如,如果usTick中的当前时间为63290061063,则有时该值为126580061060。如果你看到它是双倍的 类似地,我得到的另一个实例是当前时间是45960787154,但usTick显示为91920787152C 将纳秒转换为微秒,c,multithreading,C,Multithreading,我正在使用下面的代码将nano转换为micro-sec 这段代码主要运行罚款,但有时我看到usTick给出的值远远超过当前时间 例如,如果usTick中的当前时间为63290061063,则有时该值为126580061060。如果你看到它是双倍的 类似地,我得到的另一个实例是当前时间是45960787154,但usTick显示为91920787152 typedef unsigned long long TUINT64 unsigned long long GetMonoUSTick() {
typedef unsigned long long TUINT64
unsigned long long GetMonoUSTick()
{
static unsigned long long usTick;
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
usTick = ((TUINT64)t.tv_nsec) / 1000;
usTick = usTick +((TUINT64)t.tv_sec) * 1000000;
return usTick;
}
听起来您正在使用线程,有时两个线程会同时调用此函数。因为
usTick
是静态的
,所以它们使用相同的变量(而不是两个不同的副本)。它们都将纳秒转换为微秒,并依次分配给usTick
,然后将秒转换为微秒,并将秒添加到usTick
(因此秒添加两次)
编辑-我提出的以下解决方案基于两个假设:
- 如果两个威胁同时调用该函数,则
返回的当前时间之间的差异将太小而无关紧要(线程计算的结果之间的差异最多为clock_gettime()
)1
- 在大多数现代CPU上,读取/写入整数是一个原子操作
usTick=((TUINT64)t.tv\u nsec)/1000代码>
usTick=usTick+((TUINT64)t.tv_sec)*1000000代码>
致:
usTick=((TUINT64)t.tv\u nsec)/1000+((TUINT64)t.tv\u sec)*1000000代码>
我的解决方案的问题是,即使后面的假设是正确的,它也可能不会持续long
。因此,例如,这可能发生:
- 线程A和线程B几乎同时调用函数
- 线程A以微秒为单位计算当前时间为
0x02B3 1F02 FFFF FFFF
- 线程B以微秒为单位计算当前时间为
0x02B3 1F03 0000 0000
- 线程A将最低有效32位(
0xFFFF FFFF
)写入usTick
- 线程B将最低有效32位(
0x0000
)写入usTick
)
- 线程B将最高有效的32位(
0x02B3 1F03
)写入usTick
- 线程A将最高有效的32位(
0x02B3 1F02
)写入usTick
然后函数将在两个线程中返回0x02B3 1F02 0000
,该函数将在4294967295
关闭
正如@alk所说,如果同一进程的多个线程同时并行访问变量以读/写或写/写这些变量,则使用互斥锁来保护usTick
的读/写。这可以通过使用互斥来实现
在这种情况下,局部变量usTick
需要按照其定义静态
进行保护
使用POSIX线程,代码可能如下所示:
pthread_mutex_lock(&ustick_mutex);
usTick = ((TUINT64)t.tv_nsec) / 1000;
usTick = usTick +((TUINT64)t.tv_sec) * 1000000;
pthread_mutex_unlock(&ustick_mutex);
(为了清楚起见,遗漏了错误检查)
在使用互斥锁之前,请注意正确初始化它。在尝试任何计算之前,为什么不将纳秒转换为long-long?长的不够长吗?这是一个现有的代码,我在这里调试一些问题。我也不明白为什么这里使用static,但不知道它会造成任何危害。您还应该检查返回值clock\u gettime()
请提供一个简单的工作示例。没有复制粘贴错误。不希望在该网站上出现此类评论。那是复制粘贴错误,真的吗?你这样的“错误”是在浪费每个人的时间。重新加载/更新/修复你的操作系统外壳,这样它就不会在剪贴板上出错,否则你应该向@Anu等道歉。因为你在上面指出了错误:(SiggiSv-非常感谢。是的,我们使用线程,两个线程可以使用此功能。再次感谢同时使用的lotIf。你的第二个版本没有帮助(很多).并发读/写(写/写)必须保护对usTick
的访问。例如,这可以通过使用互斥来实现。因此,您的诊断是正确的,建议的解决方案是不正确的。@alk您是对的。我最近没有使用线程,所以我记得足够多,可以看到问题,但不足以为问题提供正确的解决方案。我建议的解决方案是基本的d基于两个假设:a)如果两个威胁同时调用该函数,则clock\u gettime()
返回的当前时间之间的差异将太小而无关紧要。b) 在大多数现代CPU上,读取/写入整数是一个原子操作(但即使这是正确的,它也可能无法保持long
)。我将编辑我的答案。感谢大家提出的解决方案。我会小心并测试它。再次感谢。