【问题标题】:Android Multi Threading with native code使用本机代码的 Android 多线程
【发布时间】:2013-05-31 18:04:08
【问题描述】:

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

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

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

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

请帮忙。

【问题讨论】:

    标签: android concurrency java-native-interface


    【解决方案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 参数。

    【讨论】:

    • 嗨,亚历克斯,我有点困惑。在您的第二段中,您提到 ReleasePrimitiveArrayCritical() 将覆盖 Java 数组的所有元素,即使其中一些元素已被另一个线程更改。如果是这种情况,那么使用 GetPrimitiveArrayCritical+ReleasePrimitiveArrayCritical 的多线程对我的问题不起作用。然后您说 GetPrimitiveArrayCritical() 始终将数组锁定到位。您能否指出我可以找到更多相关文档的方向?谢谢。
    • 对不起,我的解释令人困惑。我试图详细说明,请参阅更新的答案。
    • FWIW,在开发人员设备上,您可以配置 JNI,以便它始终尽可能复制数据。这旨在帮助追踪某些类型的错误。 forcecopy 模式还会在缓冲区之前和之后放置保护区域,并在释放缓冲区时检查它们。见milk.com/kodebase/dalvik-docs-mirror/docs/…
    • @fadden:很酷,它是一个重要的验证工具。这无助于了解客户设备上的性能情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    相关资源
    最近更新 更多