我正在研究涉及大量并发编程的Android项目,我将实现一些自定义的线程间通信内容( java.util.concurent 中的那个不太适合我的目的)。
并发编程一般不容易,但对Dalvik来说似乎更难。要获得正确的代码,您应该了解一些具体的事情以及Dalvik出现问题的地方。我找不到关于Dalvik VM的详细文档。大多数Android资源(甚至 developer.android.com 专注于平台API,并未提供有关某些非平凡(或低级)内容的任何深层信息)。
例如,Dalvik VM遵循哪个版本的 Java语言规范?根据答案,volatile
变量的处理方式不同,会影响使用volatile
变量的任何并发代码。
已经存在一些相关问题:
以及 fadden 的一些答案非常有用,但我仍然希望对相关问题有更详细和完整的理解。
所以在我感兴趣的原始问题之下(如果有必要,我将更新列表,因为以前的问题的答案将会到达):
volatile
变量的语义支持有多完整?在Double checked locking in Android fadden 中提供以下评论:
烨。通过添加“volatile”关键字,这将适用于单处理器(所有Android版本)和SMP(3.0“蜂窝”及更高版本)
这是否意味着三星Galaxy SII 具有双核CPU但只有Android 2.3可能会错误地执行并发代码? (当然Galaxy只是一个例子,关于任何具有Android 3.0前平台的多核设备的问题)
在Is Dalvik's memory model the same as Java's? fadden 中,使用以下句子提供答案:
目前没有发布的Dalvik版本与JSR-133
完全正确
这是否意味着任何现有的正确并发Java代码在发布此评论的任何Android版本上可能无法正常工作?
@gnat发表评论:
@Alexey Dalvik不符合任何JLS版本,因为一致性要求通过JCK,这不是Dalvik的选项。 这是否意味着您甚至无法应用标准Java编译器,因为它符合标准规范?是否重要?如果有,怎么样?
好吧,我的问题有点含糊不清。我实际上的意思是 JLS 不仅是Java编译器实现的规则,而且是任何 JVM 实现的隐式指南。实际上,例如, JLS 表明某些类型的读写是原子操作。编译器编写器不是很有趣,因为读/写只是转换成单个操作码。但是对于任何 JVM 实现来说,应正确实现这些操作码是必不可少的。现在你应该看看我在说什么。虽然Dalvik接受并执行使用标准Java编译器编译的程序,但 没有任何保证 表明它们已正确执行 (正如您所料),因为没有人(Dalvik的开发人员除外)知道Dalvik是否支持该程序中使用的所有JLS功能。
很明显 JCK 不是Dalvik的选项而且没关系,但是程序员真的应该知道 JLS 的功能他们可能会在Dalvik上执行代码时依赖它们。但是在文档中没有任何关于此的话。虽然您可能期望像=,+, - ,*等这样的最简单的运算符可以正常工作,因为您需要关于非平凡的功能,如volatile
变量的语义(这是不同的第二版和第三版 JLS )?后者不是你在 JLS 中找到的最重要的东西,尤其是 Java Memory Model 。
答案 0 :(得分:2)
我没有完全读完你的问题, 但首先不要使用volatile,即使是opengles,编码器也不会将它用于不同的ui vs渲染器线程。
当且仅当一个线程写入时才使用volatile(比如某些类的静态属性) 和其他读取,即使这样你必须同步,阅读这个以获得处理计数的一些好方法
How to synchronize a static variable among threads running different instances of a class in java?
答案 1 :(得分:1)
我认为您回答了自己的问题,虽然您没有详细说明为什么java.util.concurrent包不能满足您的需求,但大多数移动应用程序只使用异步IO和最少的线程。这些设备不是能够进行严格分布式处理的超级计算机,因此我很难理解为什么java.util.concurrent不能满足您的需求。
其次,如果你对Dalvik实现有疑问,以及它是否符合JLS(它没有),那么似乎有理由认为对线程机制唯一可靠的支持是语言定义的那些 - java.util。并发,可运行和线程本地存储。
在内置语言支持之外滚动任何东西只会引发麻烦,正如您的问题所暗示的那样,Dalvik可能无法以一致的方式支持。
与往常一样,当你认为你可以比编写Java的人更好地进行线程化时,请再想一想。
答案 2 :(得分:0)
<复制自评论> Dalvik不符合任何JLS版本,因为一致性要求传递JCK,这不是Dalvik的选项。 < /从评论中复制>
程序员确实应该知道在Dalvik上执行代码时他们可能依赖的JLS的哪些功能
我认为他们知道的唯一方法是学习Dalvik测试套件(我打赌有一个,我希望它是开源的不是吗?)。对于您需要的任何功能,1)尝试找到一个测试,如果您的功能实现不正确,将会失败,并检查测试是否足够好。如果没有这样的测试或者它不够好,1a)添加新的或改进现有的测试。然后,2)找出测试是否已针对您的目标实现成功运行。如果测试没有运行,那么2a)自己运行并找出它是通过还是失败。
以上BTW大致是关于 JCK 的工作原理。主要区别在于,必须为Dalvik投入自己的时间和精力,因为从Sun / Oracle获得的东西是理所当然的。另一个差异似乎是对于Dalvik而言,没有记录,而 Snorcle 在该iirc上有明确的文档
但在文档中没有任何关于此的话。
如果没有任何言论,那么我会说Dalvik文档的质量不是最理想的。轻声说话
答案 3 :(得分:0)
这是诚实的答案。如果java.util.concurrent不适合您的实现任务,那么您的问题不是java.util.concurrent,而是您的原始设计规范。重新审视您的设计,也许在这里发布您的设计中使用简单的互斥体无法完成的任务,然后社区可以向您展示如何更好地设计它。