c++ - rand_r 是否是真正的线程安全的?

标签 c++ c

嗯,rand_r 函数应该是一个线程安全函数。然而,通过它的实现,我不敢相信它可以使自己不被其他线程改变。 假设两个线程将使用相同的变量种子同时调用 rand_r。 所以会发生读写竞争。 下面列出了 glibc 实现的代码 rand_r。有人知道为什么 rand_r 被称为线程安全的吗?

 int
    rand_r (unsigned int *seed)
    {
      unsigned int next = *seed;
      int result;

      next *= 1103515245;
      next += 12345;
      result = (unsigned int) (next / 65536) % 2048;

      next *= 1103515245;
      next += 12345;
      result <<= 10;
      result ^= (unsigned int) (next / 65536) % 1024;

      next *= 1103515245;
      next += 12345;
      result <<= 10;
      result ^= (unsigned int) (next / 65536) % 1024;

      *seed = next;

      return result;
    }

最佳答案

您可以想到线程安全的三个级别,为了便于引用,我将在此处编号。

1) 根本不是线程安全的。从多个线程并发调用该函数是不安全的。例如,strtok

2) 相对于系统线程安全。从多个线程并发调用该函数是安全的,前提是不同的调用对不同的数据进行操作。例如,rand_rmemcpy

3) 关于数据的线程安全。从多个线程并发调用该函数是安全的,即使作用于相同的数据也是如此。例如 pthread_mutex_lock

rand_r 处于第 2 级,C 上下文中的约定(特别是在 POSIX 规范中)将其称为“线程安全”。

在其他一些语言中,例如 Java,惯例是将级别 3 称为“线程安全”,将其他所有内容称为“非线程安全”。因此,例如 java.util.Vector 是“线程安全的”,而 java.util.ArrayList 是“非线程安全的”。当然 java.util.ArrayList 的所有方法都在第 2 层。所以来自 Java 的程序员可能会自然地调用 rand_rmemcpy ”不是线程安全的”。

在 C 语言中,约定是不同的,也许是因为内部同步的数据结构一开始就很少见。在 C 的上下文中,您可能会问“文件句柄是线程安全的吗?”,并且谈论的是级别 3,但是当问“这个函数是线程安全的吗?”时这通常意味着 2 级。

关于c++ - rand_r 是否是真正的线程安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2772090/

相关文章:

c++ - 可变参数模板求和类

c++ - CMake 在链接之前指定源

c - 全局值(value)没有得到体现

c++ - STL 绳索 - 何时何地使用

c++ - 控制线程异步执行时间

c - 为什么 int x[n] 错误,其中 n 是 const 值?

c - fork() 打印两次之前的语句

c - 在函数中定义宏值

php - swig-php 包装器使用指针,c 代码是一个数组

c++ - 为什么一个结构有另一个结构作为成员包装在一个 union 中,如果没有显式默认构造函数则不能编译?