1

我正在做一个android项目,发现一个操作成为性能瓶颈。此操作适用于大型数组 A 并将结果存储到另一个数组 B 中。

我发现这个操作可以并行化。数组A可以分成N个更小的段。该操作可以独立地对每个段进行操作,并将结果存储到 B 中的相应段中。

该操作使用本机代码编写,带有 GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical 对以访问数组 A 和 B。

我的问题是,如果使用多线程,GetPrimitiveArrayCritical(pEnv, A, 0) 将从不同的线程多次调用。GetPrimitiveArrayCritical 是否阻塞?即,如果一个线程进行此调用,第二个线程能否在第一个线程调用 ReleasePrimitiveArrayCritical() 之前进行相同的调用?

请帮忙。

4

1 回答 1

1

是的,您可以GetPrimitiveArrayCritical()从两个并发线程调用。该函数不会阻塞,并且您的两个线程将授予本机代码对底层数组的访问权限。但另一方面,该函数不会同步此访问,即如果线程 1 更改索引 100 处的值,并且线程 2 也更改索引 100 处的值,您不知道最后会选择哪个.

如果您不写入数组,则保证您得到正确的服务。不要忘记ReleasePrimitiveArrayCriticalJNI_ABORT标志。

如果要写入数组,请检查GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)isCopy设置的输出参数。如果结果为 0,您可以安全地继续使用多线程方法。

如果结果不为 0,ReleasePrimitiveArrayCritical()将覆盖 Java 数组的所有元素,即使其中一些元素在 Java 或 C 中的不同线程中被更改。如果您的程序检测到这种情况,它必须释放数组(使用JNI_ABORT)并等待其他线程完成。在 Android 上,我从未见过数组被复制,它们总是被锁定在原地。但是没有人会保证这不会发生在您身上,无论是在当前系统中还是在未来的版本中。

这就是为什么你必须检查isCopy参数。

于 2013-06-01T18:56:53.543 回答