47 votes

Dalvik VM et modèle de mémoire Java (programmation simultanée sur Android)

Je travaille sur des projets Android qui impliquent beaucoup de programmation concurrente et je vais implémenter des fonctions de communication inter-threads personnalisées (celles de la section java.util.concurent ne sont pas bien adaptés à mes besoins).

La programmation concurrente n'est pas facile en général, mais avec Dalvik, cela semble être encore plus difficile. Pour obtenir un code correct, vous devez connaître certaines choses spécifiques et c'est là que le problème se pose avec Dalvik. Je n'arrive pas à trouver une documentation détaillée sur la VM Dalvik. La plupart des ressources Android (même les développeur.Android.com se concentre sur l'API de la plateforme et ne fournit pas d'informations approfondies sur certaines choses non triviales (ou de bas niveau)).

Par exemple, à quelle édition de Spécification du langage Java la VM Dalvik est conforme ? En fonction de la réponse, le traitement de volatile sont différentes et affectent le code concurrent qui utilise la variable volatile variables.

Il y a déjà quelques questions connexes :

et quelques réponses par fadden sont très utiles, mais je souhaite toujours obtenir une compréhension plus détaillée et complète de la matière en question.

Voici donc une liste de questions brutes qui m'intéressent (je mettrai la liste à jour si nécessaire, au fur et à mesure que les réponses aux questions précédentes arriveront) :

  1. Où trouver les détails sur la VM Dalvik qui peuvent fournir les réponses aux questions ci-dessous ?

  2. A quelle édition de Spécification du langage Java la VM Dalvik est conforme à ?

  3. Si la réponse à la question (2) est "troisième édition", alors dans quelle mesure le soutien des Dalviks à l'initiative de l'Union européenne est-il complet ? Modèle de mémoire Java défié dans ce cahier des charges ? Et surtout, quel est le degré de complétude de la prise en charge de la sémantique des volatile variables ?

  4. Dans le Double vérification du verrouillage dans Android el fadden fournir le commentaire suivant :

    Yup. Avec l'ajout du mot-clé "volatile", cela fonctionnera sur uniprocesseur (toutes les versions d'Android) et SMP (3.0 "honeycomb" et ultérieures)

    Est-ce que cela signifie que Samsung Galaxy SII qui a un processeur à double cœur mais seulement Android 2.3 peut exécuter le code concurrent de manière incorrecte (bien sûr, Galaxy n'est qu'un exemple, la question concerne tout appareil multicœur avec une plateforme pré-Android 3.0).

  5. Dans le Le modèle de mémoire de Dalvik est-il le même que celui de Java ? el fadden donnez la réponse à l'aide de la phrase suivante :

    Aucune version de Dalvik actuellement disponible n'est entièrement correcte en ce qui concerne la JSR-133.

    Cela signifie-t-il que tout code Java concurrent correct existant peut fonctionner incorrectement sur toute version d'Android publiée à la date de publication de ce commentaire ?

Update#1 : Réponse au commentaire de @gnat (trop long pour être un commentaire aussi)

@gnat poster un commentaire :

@Alexey Dalvik n'est conforme à aucune édition de JLS, car la conformité nécessite de passer le JCK, ce qui n'est pas une option pour Dalvik. Cela signifie-t-il que vous ne pouvez même pas utiliser le compilateur Java standard parce qu'il est conforme aux spécifications standard ? Cela a-t-il une importance ? Si oui, comment ?

Eh bien, ma question était en quelque sorte ambiguë. Ce que je voulais dire en fait c'est que JLS n'est pas seulement les règles pour les implémentations du compilateur Java mais aussi une implicite des directives pour tout JVM mises en œuvre. En effet, JLS par exemple, stipule que la lecture et l'écriture de certains types sont atomique opérations. Ce n'est pas très intéressant pour l'auteur du compilateur parce que la lecture/écriture est traduite en un seul opcode. Mais il est essentiel pour tout JVM mise en œuvre qui devrait mettre en œuvre ces opcodes correctement. Maintenant vous devriez voir de quoi je parle. Alors que Dalvik accepte et exécute les programmes compilés avec le compilateur standard de Java, il y a aucune garantie qu'ils sont exécutés correctement (comme vous pouvez vous y attendre) juste parce que personne (sauf peut-être les développeurs de Dalvik) ne sait si toutes les fonctionnalités de JLS utilisées dans le programme sont supportées par Dalvik.

Il est clair que JCK n'est pas une option pour Dalvik et c'est Ok, mais les programmeurs devraient vraiment savoir sur quel caractéristiques de JLS ils peuvent compter quand ils exécutent leur code sur Dalvik. Mais il n'y a aucun mot à ce sujet dans la documentation. Bien que l'on puisse s'attendre à ce que les opérateurs les plus simples comme =, +, -, *, etc. fonctionnent comme prévu, qu'en est-il des opérateurs non triviaux ? caractéristiques comme la sémantique de volatile variables (ce qui est différent dans les 2e et 3e éditions de JLS ) ? Et ce n'est pas la chose la plus banale que l'on puisse trouver dans les documents suivants JLS et particulier dans Modèle de mémoire Java .

2voto

GLES Points 2462

Je n'ai pas lu entièrement votre question, mais tout d'abord n'utilisez pas de volatile, même les codeurs d'opengles ne l'utilisent pas pour les différents threads de l'interface utilisateur et du moteur de rendu.

Utiliser volatile si et seulement si un thread écrit (disons à la propriété statique d'une classe) et l'autre lit, même dans ce cas vous devez synchroniser, lisez ceci pour quelques bonnes façons de gérer les comptes

Comment synchroniser une variable statique entre des threads exécutant différentes instances d'une classe en java ?

  1. toujours utiliser la synchronisation
  2. ne pas se lancer dans de grands projets pour des sujets aussi difficiles que la programmation concurrente
  3. parcourir les échantillons Android sur les jeux où ils ont abordé le concept de runnables, les gestionnaires et l'échange de messages entre les threads (UI THREAD et RENDER THREAD).

1voto

deleted_user Points 3118

Je pense que vous avez répondu à votre propre question, bien que vous n'ayez donné aucun détail sur la raison pour laquelle le paquet java.util.concurrent ne répond pas à vos besoins. La plupart des applications mobiles utilisent simplement des entrées/sorties asynchrones et un minimum de threading. Ces appareils ne sont pas des super ordinateurs capables d'un traitement distribué sérieux, j'ai donc un peu de mal à comprendre pourquoi java.util.concurrent ne répond pas à vos besoins.

Deuxièmement, si vous vous posez des questions sur l'implémentation Dalvik et sur sa conformité à la JLS (ce n'est pas le cas), il semblerait que le seul support fiable pour les mécanismes de threading soit celui que le langage définit - java.util.concurrent, runnable et thread local storage.

L'intégration de tout ce qui n'est pas pris en charge par le langage intégré ne peut que créer des problèmes et, comme le suggère votre question, ne sera probablement pas pris en charge de manière cohérente par Dalvik.

Comme toujours, lorsque vous pensez que vous pouvez faire du threading mieux que les gars qui ont écrit Java, détrompez-vous.

0voto

gnat Points 5565

<copied from comment> Dalvik ne se conforme à aucune édition de JLS, parce que la conformité exige de passer JCK ce qui n'est pas une option pour Dalvik. </copied from comment>

Les programmeurs doivent vraiment savoir sur quelles fonctionnalités de JLS ils peuvent compter lorsqu'ils exécutent leur code sur Dalvik.

Je pense que la seule façon pour eux de le savoir est d'étudier la suite de tests Dalvik (je parie qu'il y en a une et je suppose qu'elle est open source, n'est-ce pas ?) Pour toute fonctionnalité dont vous avez besoin, 1) essayez de trouver un test qui échouerait si votre fonction est implémenté de manière incorrecte et vérifier si le test est suffisamment bon. Si ce test n'existe pas ou s'il n'est pas assez bon, 1a) ajouter un nouveau test ou améliorer le test existant. Ensuite, 2) vérifiez si le test a été exécuté avec succès contre votre implémentation cible. Si le test n'a pas été exécuté, 2a) exécutez-le vous-même et découvrez s'il réussit ou échoue.

BTW ci-dessus est à peu près comment JCK travaux. La principale différence est que l'on doit investir son propre temps et ses propres efforts avec Dalvik pour des choses que Sun/Oracle nous donne pour acquis. Une autre différence semble être que pour Dalvik, cela n'est pas documenté, alors que pour Sun/Oracle, cela ne l'est pas. Snorcle a des documents clairs à ce sujet, je crois

Mais il n'y a aucun mot à ce sujet dans la documentation.

Eh bien, s'il n'y a pas de mots sur ce sujet, je dirais que la qualité de la documentation Dalvik est sous-optimale. En parlant doucement

0voto

Gimballon Points 66

Voici la réponse honnête. Si java.util.concurrent n'est pas à la hauteur de votre mise en œuvre, alors votre problème n'est pas java.util.concurrent mais plutôt les spécifications de votre conception originale. Réexaminez votre conception, postez ici ce qui, dans votre conception, fait que l'utilisation de mutex simples n'est pas à la hauteur de votre tâche, puis la communauté pourra vous montrer comment améliorer votre conception.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X