Android JNI - 线程同步
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android JNI - 线程同步相关的知识,希望对你有一定的参考价值。
我有一个本机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
在set之前被调用。如何解决线程同步问题?我无法编辑底层API。
我在考虑在每个JNI方法中使用std::unique_lock
并创建我将锁定的全局std::mutex
变量。这是一个好方法,还是有一些“标准”JNI方式(我发现有可以从env访问的监视器)。
我也经常调用get(它是在OpenGL渲染循环期间),因此性能至关重要。
答案
锁定互斥锁的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
。
或者,如果您只需要锁定C ++代码内部的结构,请使用带有std::mutex
的静态lock_guard
。
以上是关于Android JNI - 线程同步的主要内容,如果未能解决你的问题,请参考以下文章