我有一个本机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());
}
一切正常。但是,可以从不同的线程访问get
和set
方法,在这种情况下,有时会在设置之前调用get
。如何解决线程同步问题?我无法编辑底层API。
我在考虑在每个JNI方法中使用std::unique_lock
并创建我将锁定的全局std::mutex
变量。这是一个好方法,还是有一些"标准" JNI方式(我发现有可从env访问的监视器)。
我也经常调用get(这是在OpenGL渲染循环期间),因此性能至关重要。
答案 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
。