C 将纳秒转换为微秒

C 将纳秒转换为微秒,c,multithreading,C,Multithreading,我正在使用下面的代码将nano转换为micro-sec 这段代码主要运行罚款,但有时我看到usTick给出的值远远超过当前时间 例如,如果usTick中的当前时间为63290061063,则有时该值为126580061060。如果你看到它是双倍的 类似地,我得到的另一个实例是当前时间是45960787154,但usTick显示为91920787152 typedef unsigned long long TUINT64 unsigned long long GetMonoUSTick() {

我正在使用下面的代码将nano转换为micro-sec

这段代码主要运行罚款,但有时我看到usTick给出的值远远超过当前时间

例如,如果usTick中的当前时间为63290061063,则有时该值为126580061060。如果你看到它是双倍的

类似地,我得到的另一个实例是当前时间是45960787154,但usTick显示为91920787152

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
)。我将编辑我的答案。感谢大家提出的解决方案。我会小心并测试它。再次感谢。