2013-05-31 49 views
1

我正在开发一个android项目,并发现某个操作成为性能瓶颈。此操作对大阵列A起作用,并将结果存储到另一个阵列B.使用本机代码进行Android多线程处理

我发现此操作可以并行化。阵列A可以分成N个较小的片段。该操作可在各段独立工作,并将结果存储到一个相应的分段中B.

操作是写在与GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical对本机代码来访问阵列A和B

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

请帮忙。

回答

1

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

如果您不写入数组,则保证您的服务正确无误。不要忘记ReleasePrimitiveArrayCriticalJNI_ABORT国旗。

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

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

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

+0

嗨亚历克斯,我有点困惑。在第二段中,您提到ReleasePrimitiveArrayCritical()将覆盖Java数组的所有元素,即使其中一些元素被另一个线程更改了。如果是这种情况,那么使用GetPrimitiveArrayCritical + ReleasePrimitiveArrayCritical的多线程不适用于我的问题。然后你说GetPrimitiveArrayCritical()总是将数组就地锁定。你能否指点我能找到更多文件的方向?谢谢。 – windchime

+0

对不起,我的解释很混乱。我试图阐述,看到更新的答案。 –

+1

FWIW,开发设备上可以配置JNI,使其始终将数据只要有可能。这旨在帮助追踪某些类型的错误。 forcecopy模式还会在缓冲区之前和之后放置防护区,并在释放缓冲区时检查它们。见http://milk.com/kodebase/dalvik-docs-mirror/docs/embedded-vm-control.html#checkjni。 – fadden