C99:限制指针记录线程安全?

Lou*_*uis 5 c concurrency c99 mutability restrict-qualifier

这个问题不是关于限制的技术用法,更多是关于主观使用的.虽然我可能会误解技术上的限制是多么有限,但在这种情况下,你应该随意烧我,以便在错误的前提下提出问题.

以下是我到目前为止如何使用限制的两个示例:

如果我有一个指向一系列不可变字符的函数的函数,我不说它是受限制的,因为允许其他人在函数执行的同时通过自己的指针访问数据,例如从另一个并行执行线.数据没有被修改,所以没问题.

但是,如果函数接受指向它可能修改的可变字符序列的指针,我说它是受限制的,因为在执行期间绝对不应该从任何指针(显然是函数使用的参数)中访问数据.由于可能不一致的数据导致的功能.它还说明了数据被修改的可能性,因此编码器知道不读取陈旧数据,并且他们在访问时应该使用内存屏障或者其他......

我没有编写很多C代码,所以我很容易对我在这里假设的内容提出错误.这是对限制的正确用法吗?在这种情况下值得做吗?

我还假设一旦限制指针在函数返回时弹出堆栈,那么数据可以再次通过任何其他指针自由访问,并且限制仅持续与受限指针一样长.我知道这依赖于遵循规则的编码器,因为通过"非官方"指针访问受限数据是UB.

我有这一切吗?

编辑:

我只想说清楚我已经知道它绝对没有阻止用户通过多个线程访问数据,我也知道C89甚至不知道'线程'是什么.

但是考虑到可以通过引用修改参数的任何上下文,很明显它不能在函数运行时被访问.这对强制执行线程安全没有任何作用,但它确实清楚地表明在执行函数期间通过自己的指针修改数据需要您自担风险.

即使线程完全脱离了等式,你仍然允许在我认为正确的场景中进一步优化.

即便如此,感谢您迄今为止的所有权威答案.我是否赞成我喜欢的所有答案,或者仅仅是我接受的答案?如果接受不止一个怎么办?对不起,我是新来的,现在我会更全面地浏览常见问题解答......

Nem*_*emo 5

restrict与线程安全无关.事实上,现有的C标准根本没有关于线程的话题; 从规范的角度来看,没有"线程"这样的东西.

restrict是一种通知编译器有关别名的方法.指针经常使编译器难以生成有效的代码,因为编译器在编译时无法知道两个指针是否实际引用相同的内存.玩具示例:

void foo(int *x, int *y) {
    *x = 5;
    *y = 7;
    printf("%d\n", *x);
}
Run Code Online (Sandbox Code Playgroud)

当编译器处理此函数时,它不知道是否x并且y引用相同的内存位置.因此,它不知道它是否将打印5或者7,它具有发射代码实际读取*x之前调用printf.

但是,如果你声明xint *restrict x,编译器可以证明该函数打印5,因此它可以为printf调用提供编译时常量.

很多这样的优化变得可能restrict,尤其是在谈论数组操作时.

但这些都与线程没有任何关系.要正确使用多线程应用程序,您需要适当的同步原语,如互斥锁,条件变量和内存屏障......所有这些都是特定于您的平台的,并且没有任何与之相关的内容restrict.

[编辑]

要回答关于使用restrict文档形式的问题,我也会对此说"不".

您似乎在考虑应该记录何时可以或不能同时访问变量.但对于共享数据,适当的规则(几乎总是)确保永远不会同时访问它.

用于可变相关文档是否它是在所有共享和其互斥保护它.任何因任何原因访问该变量的代码,甚至只是为了读取它,都需要保存互斥锁.作者既不知道也不关心某个其他线程是否可能或者可能不会同时访问变量...因为其他线程将遵循相同的规则,并且互斥锁保证不存在并发访问.

这个规则很简单,有效,并且可以扩展,这就是为什么它是在线程之间共享数据的主要范例之一.(另一个是消息传递.)如果你发现自己试图推理"这次我真的需要锁定互斥锁吗?",你几乎肯定做错了什么.这一点很难夸大.