我正在为C库编写Java绑定,因此正在使用JNI。合理地,Oracle specifies应该使用多线程感知编译器编译用于Java的本机库。
JNI文档提供了一个具体示例:对于gcc
,应通过定义宏_REENTRANT
或_POSIX_C_SOURCE
中的一个来满足此多线程感知要求。这对我来说似乎很奇怪。 _REENTRANT
和_POSIX_C_SOURCE
是功能测试宏。 GCC和POSIX文档描述了它们在定义符号和使声明可见方面的效果,正如我对任何特征测试宏所期望的那样。
如果我不需要额外的符号或功能,那么这些宏实际上对我有用吗?是否有一个或两个导致gcc
生成不同于其他代码的代码?它们是否可能导致我的代码对标准库函数的调用链接到不同的实现?或者甲骨文是在谈论它的下层区域?
编辑:
此外,我发现重入是线程的一个单独考虑因素。即使对于单线程程序,非重入也可能是一个问题,因此Oracle建议定义_REENTRANT
使gcc
多线程感知现在看起来更加可疑。
答案 0 :(得分:2)
Oracle建议是针对Solaris编写的,而不是针对Linux编写的。
在Solaris上,如果您编译了.so
而没有_REENTRANT
并最终被多线程应用程序加载,那么可能会发生非常糟糕的事情(例如libc内部的随机数据损坏)。这是因为没有定义,默认情况下你会得到一些例程的未锁定变体。
当我第一次阅读这篇文档时就是这种情况,这可能是15年前,在我上次阅读本文档之后添加了对sun studio编译器的-mt
标志的提及。
现在不再是这种情况了 - 无论你是否使用_REENTRANT
标志进行编译,现在总是得到相同的例程;它现在只是一个功能宏,而不是行为宏。