繁体   English   中英

rand_r是否是实线程安全的?

[英]whether rand_r is real thread safe?

好吧,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级

rand_r是线程安全的,因为该函数是完全纯函数。 除了参数之外,它不会读取或修改任何状态。 因此可以安全地同时调用它。

这与大多数将rand (状态)(状态)保存在全局变量中的rand函数不同。

假设两个线程将使用相同的变量种子同时调用rand_r。

我假设你的意思是这样的

int globalSeed;

//thread 1
rand_r(&globalSeed);

//thread 2
rand_r(&globalSeed);

这并不意味着该函数不是线程安全的,而是意味着您通过提供输出参数来以非线程安全的方式使用它,该输出参数可以被另一个线程访问/修改。

这与将函数结果写入可以由另一个线程访问/修改的全局变量相同。 这并不意味着该函数不是线程安全的,这意味着您的代码不是线程安全的。

因为它修改了种子,所以种子被传递了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM