Dalvik VM和Java内存模型(Android上的并发编程)
我正在开发涉及大量并发编程的Android项目,我将实现一些自定义的线程间通信(来自java.util.concurent的一个不适合我的目的)。
并发编程并不容易,但对于Dalvik而言似乎更难。 要获得正确的代码,您应该了解一些具体的事情,以及Dalvik出现的问题。 我只是找不到有关Dalvik VM的详细文档。 大多数Android资源(甚至是developer.android.com都关注平台API,并不提供任何关于一些不平凡(或低级)事物的深层信息)。
例如,Dalvik VM符合哪个版本的Java语言规范 ? 根据回答, volatile
variables的处理是不同的,并影响使用volatile
variables的任何并发代码。
已经有一些相关的问题了:
- Dalvik的内存模型和Java的一样吗?
- 在Android中双击lockinglocking
fadden的一些答案是非常有用的,但我仍然想要得到更详细和完整的问题的理解。
所以在下面的一个原始问题我很有趣(我会更新列表,如有必要,以前的问题的答案将到达):
- 在哪里可以find有关Dalvik VM的详细信息,可以为下面的问题提供答案。
- Dalvik VM符合哪个版本的Java语言规范 ?
- 如果对(2)的回答是“第三版”,那么在本规范中Dalviks对Java存储器模型的支持有多完善呢? 特别是如何完成对
volatile
variables语义的支持? -
在Android的Double checked locking中 , fadden提供了以下注释:
对。 随着“易变”关键字的增加,这将工作在单处理器(所有版本的Android)和SMP(3.0“蜂窝”和更高版本)
这是否意味着具有双核CPU但只有Android 2.3的三星Galaxy SII可能会错误地执行并发代码? (当然,Galaxy仅仅是一个例子,问题在于Android 3.0平台之前的多核设备)
-
在Dalvik的内存模型中是否和Java一样? 法登提供了以下句子的答案:
目前没有任何Dalvik版本对于JSR-133来说是完全正确的
这是否意味着任何现有的正确的并发Java代码可能在发布此评论之前发布的任何Android版本上工作不正确?
更新#1:回答@ gnat的评论(太长,以至于评论)
@gnat发表评论:
@Alexey Dalvik不符合任何JLS版本,因为一致性要求传递不是Dalvik选项的JCK。 这是否意味着你甚至不能使用标准的Java编译器,因为它符合标准规范? 那很重要吗? 如果是的话,怎么样?
那么,我的问题是不明确的。 我的意思是, JLS不仅是Java编译器实现的规则,而且是任何JVM实现的隐含指导。 事实上,例如, JLS指出,某些types的读写是primefaces操作。 编译器编写器不是很有趣,因为读/写只是转换成一个操作码。 但对于任何应该正确实现这些操作码的JVM实现来说,这是非常重要的。 现在你应该看看我在说什么。 虽然Dalvik接受和执行用标准Java编译器编译的程序,但是没有任何担保它们是正确执行的(正如你所期望的),因为没有人(除了Dalvik的开发者)知道程序中使用的所有JLS特性是否被Dalvik的。
很显然, JCK不是Dalvik的select,这是可以的,但程序员真的应该知道在Dalvik上执行代码时,他们可能依赖哪些JLS 特性 。 但在文档中没有关于这个的任何说法。 虽然你可能会期望最简单的运算符,如=,+, – ,*等是如你所期望的那样工作,如volatile
variables的语义(这在JLS的第二和第三版本中是不同的) 而后者并不是在JLS中可以find的最不平凡的东西,特别是在Java内存模型中 。
我没有完全读你的问题,但首先不要使用易失性,即使opengles编码器不使用它为不同的UI和渲染线程。
使用volatile当且仅当一个线程写入(对一些类的静态属性说)和其他读取,即使那么你必须同步,阅读这个一些好方法来处理计数
如何在Java中运行不同类实例的线程之间同步静态variables?
- 总是使用同步
- 不要在大型项目中跳出像并发编程这样的难题
- 通过游戏中的android样本,讨论了runnables,处理程序和交换消息(不包括线程(UI线程和RENDER线程))的概念。
我认为你回答了你自己的问题,尽pipe你没有提供关于为什么java.util.concurrent包不适合你的需求的细节,但大多数移动应用程序只是使用asynchronousIO和最less的线程。 这些设备不是超级计算机能够进行严格的分布式处理,所以我有点难以理解为什么java.util.concurrent不会满足您的需求。
其次,如果您对Dalvik实现有疑问,是否符合JLS(它并不),那么似乎有理由认为对线程机制的唯一可靠支持就是语言定义的那些 – java.util.concurrent,runnable和线程本地存储。
在内置的语言支持之外滚动任何东西只是要求麻烦,而且正如你的问题所暗示的,Dalvik可能不会以一致的方式支持。
像往常一样,当你认为你可以比编写Java的人更好地进行线程化时,再想一想。
Dalvik不符合任何JLS版本,因为一致性要求传递不是Dalvik选项的JCK 。 </从评论复制>
程序员真的应该知道他们在Dalvik上执行代码时可能依赖哪些JLS特性
我认为他们知道的唯一方法就是学习Dalviktesting套件(我打赌有一个,我认为它是开源的不是吗?)。 对于你需要的任何function,1)尝试find一个testing,如果你的function被错误地执行,并检查testing看起来是否足够,将会失败。 如果没有这样的testing或者不够好,1a)增加新的或改进现有的testing。 然后,2)找出testing是否已经成功地针对您的目标实施运行。 如果testing没有运行,那么2a)自己运行,看看它是否通过或失败。
顺便说一下,大概是JCK如何工作。 主要区别在于,必须为Dalvik投入自己的时间和精力才能从Sun / Oracle获得理所当然的事情。 另一个区别似乎是Dalvik这个没有logging,而Snorcle在这个iirc上有清晰的文档
但在文档中没有关于这个的任何说法。
以及如果没有这个话,那么我会说Dalvik文档的质量是不理想的。 轻轻地说
这是诚实的答案。 如果java.util.concurrent不适合您的实现,那么您的问题不是java.util.concurrent,而是您的原始devise规范。 重温你的devise,也许在这里发表你的devise使用简单的互斥体不适合你的任务,然后社区可以告诉你如何更好地devise它。