假设我的游戏应用程序中有两个线程(除主线程外):
> glrenderer线程(由Android的GLSurfaceVIEw.Renderer提供)
>另一个线程(游戏线程)
两个线程都使用JNI调用应用程序的某些C(即AndroID NDK)组件.
假设我在Java中分配了一个直接的IntBuffer(例如从glrenderer线程中分配,但不要假设这样).事实:
>通过本地代码从glrenderer线程读取此直接缓冲区(即,通过JNI调用的C组件)
>此直接缓冲区有时是从其他线程(游戏线程)写入的
在以下两种情况下,什么是(最好的)同步方式(实际上是确保数据可见性),即保证glrenderer代码中的本机代码看到最新的IntBuffer内容?
>场景1:游戏线程的Java代码写入IntBuffer(例如,通过IntBuffer.put())
>场景2:游戏线程调用的本机代码写入IntBuffer
我以为标准的Java同步将适用于两种情况:
public voID onDrawFrame(GL10 gl) { // the glrenderer thread // ... synchronized (obj) { callNativeCode1(); // a JNI call; this is where the C++ native code reads the IntBuffer }}public voID run() { // the game thread // ... synchronized (obj) { intBuffer.put(...); // writing the buffer from managed code } // ... synchronized (obj) { callNativeCode2(); // a JNI call; writing the buffer from C++ native code }}
解决方法:
您可以使用等效于同步的JNI来确保对两个线程访问的本机数据进行同步:
//before read/writing shared data(*env)->MonitorEnter(obj);... /* synchronized block *///after read/writing shared data(*env)->MonitorExit(obj);
您可以在此IBM article中找到更多信息.
编辑:
经过进一步的挖掘,事实证明应该如何使C代码保持同步取决于VM实现(请参阅第2.1:http://www.hdfgroup.org/hdf-java-html/JNI/节).可怕的是:
…and in most cases there is no way to kNow what the C code must do.
不幸的是,我找不到有关AndroID如何专门处理此问题的信息,也找不到关于AndroID版本之间是否一致处理该问题的信息.
但是,AndroID开发站点(http://developer.android.com/training/articles/smp.html)提供了另一个有趣的信息,该信息指示ARM cpu提供的内存一致性较弱,因此这可能是C代码的默认行为.
基本上,问题归结为:在Java中同步线程访问时,是否将同步c数据.由于链接1(http://www.hdfgroup.org/hdf-java-html/JNI/)不能给出直接的答案,而链接2(http://developer.android.com/training/articles/smp.html)表示ARM cpu提供的内存一致性较弱,因此再次使用C代码进行监视调用似乎是更安全的选择.
总结以上是内存溢出为你收集整理的Android Java本机数据可见性全部内容,希望文章能够帮你解决Android Java本机数据可见性所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)