Android JNI - 线程同步

时间:2017-12-24 07:26:16

标签: c++ multithreading android-ndk java-native-interface

我有一个本机C ++代码,我通过JNI从Android调用。

JNIEXPORT void JNICALL
Java_com_myapp_CApi_setFoo(JNIEnv *env, jobject thiz, jstring foo) {
    const char * fooStr = env->GetStringUTFChars(foo, 0);
    MyCApiSetFoo(fooStr);
    env->ReleaseStringUTFChars(foo, fooStr);
}

JNIEXPORT jstring JNICALL
Java_com_myapp_CApi_getFoo(JNIEnv *env, jobject thiz) {
    return env->NewStringUTF(MyCApiGetFoo());
}

一切正常。但是,可以从不同的线程访问getset方法,在这种情况下,有时会在设置之前调用get。如何解决线程同步问题?我无法编辑底层API。

我在考虑在每个JNI方法中使用std::unique_lock并创建我将锁定的全局std::mutex变量。这是一个好方法,还是有一些"标准" JNI方式(我发现有可从env访问的监视器)。

我也经常调用get(这是在OpenGL渲染循环期间),因此性能至关重要。

1 个答案:

答案 0 :(得分:3)

JNI锁定互斥锁的方式是MonitorEnter/MonitorExit

也就是说,您可以从java代码输入java synchronized块所在的监视器。

JNIEXPORT void JNICALL
Java_com_myapp_CApi_setFoo(JNIEnv *env, jobject thiz, jstring foo) {
    const char * fooStr = env->GetStringUTFChars(foo, 0);
    env->MonitorEnter(thiz); // same effect as synchronized(thiz) { ...
    MyCApiSetFoo(fooStr);
    env->MonitorExit(thiz);
    env->ReleaseStringUTFChars(foo, fooStr);
}

JNIEXPORT jstring JNICALL
Java_com_myapp_CApi_getFoo(JNIEnv *env, jobject thiz) {
    env->MonitorEnter(thiz);
    auto res = MyCApiGetFoo();
    env->MonitorExit(thiz);
    return env->NewStringUTF(res);
}

您可以使用任何对象锁定,如果没有提供足够级别的锁定粒度,则不必是thiz

或者,如果您只需要将结构 internal 锁定到C ++代码,请使用带有std::mutex的静态lock_guard