贵有恒,何必三更起、五更眠、最无益,只怕一日曝、十日寒。这篇文章主要讲述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渲染循环期间),因此性能至关重要。
答案【Android JNI - 线程同步】锁定互斥锁的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_log_print打印Opencv Mat,Android NDK的内容
- Facebook Buck(BUILD FAILED:没有检测到原生平台。可能没有正确配置Android NDK)
- 如何在JavaScript中从Twig安全地打印字符串变量
- 为Symfony 1.4中的异常实现自定义500错误页面
- 使用C#和Winforms捕获不同方式的屏幕截图
- 如何在Twig中重复现有的块
- 如何在Symfony 2和3中的模板上使用Twig执行原则查询
- 如何在Symfony 3中使用FFMpeg将webm视频转换为mp4
- C#中的String和string关键字有什么区别