Synchronisation

Synchronisation des threads

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

La notion de synchronisation peut être étrangère à des développeurs PHP qui doivent rarement se soucier de faire fonctionner deux éléments en parallèle. C'est pourquoi il est important pour eux de comprendre l'aspect de synchronisation en Java. L'aspect que cet article exploitera un peu plus.

Synchronized() et volatile

La première des deux autres moyens de synchronisation est le mot clé synchronized correspondant soit à une méthode, soit à un block. Il permet de coordonner l'exécution des méthodes et des variables. Grâce à lui, les Threads s'exécutent chronologiquement en garantissant la cohérence des données.

Autre moyen, le mot volatile indique qu'une variable doit être synchronisée. Autrement dit, elle ne peut pas être mis dans le cache local d'un Thread et qu'elle sera toujours lue depuis le Thread principal. Le mot volatile empêche donc le compilateur de modifier la logique d'exécution d'un traitement. Contrairement à synchronized, volatile ne bloque pas l'accès à la ressource synchronisée aux autres Threads. Il peut également agir sur les types primitifs tandis que synchronized non.

Cependant, il y a deux conditions qu'on doit remplir pour utiliser volatile dans la synchronisation :

  1. L'opération sur la variable ne peut pas dépendre de sa valeur actuelle : volatile ne peut pas être utilisé, par exemple, dans l'incrémentation d'un compteur.
  2. Ne peut pas participer dans l'opération de vérification (par exemple if-else) avec d'autres variables partagées.

Regardons deux exemples qui illustrent l'utilisation de ces deux méthodes de synchronisation. On commence avec synchronized :

afficher le code

Sur l'écran on voit l'exécution correcte :

Before incrementing 49
After incrementing 50


Before incrementing 50
After incrementing 51


Before incrementing 51
After incrementing 52


Before incrementing 52
After incrementing 53

Sans la synchronisation de la méthode increment() on risque de se trouver dans la situation où plusieurs Threads essaient d'y accéder avec la valeur d'int counter lue depuis le cache local. Voici l'exemple d'une exécution incorrecte :

Before incrementing 49




Before incrementing 50
After incrementing 50


Before incrementing 51
After incrementing 52
After incrementing 51
Before incrementing 50
After incrementing 53

Passons à l'illustration du volatile.

afficher le code

Grâce à volatile, les Threads sachent qu'il faut chercher boolean wasDone dans le Thread principal et non pas dans le cache respectif. Cependant, seule présence du volatile ne change pas grande chose. Seule sa relation avec synchronized peut garantir une meilleure coordination d'exécution.

Généralement, volatile est faiblement utilisé dans le monde des applications Java. Il est aussi peu documenté. Dans la plupart des cas, synchronized y est préféré pour une échelle plus grande de son utilisation. Dans nos exemples on suivra la tendence générale.

Un autre moyen de protéger des applications fonctionnant en mode multi-threading contre l'incohérence des données sont des objets immutables.

Bartosz KONIECZNY Concurrence

Une question ? Une remarque ?

*

*

Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil Symfony2

Comment personnaliser l'affichage des champs du formulaire ?

Pour personnaliser l'affichage des champs du formulaire sous Symfony2 on doit surcharger le paramètre nommé templating.helper.form.class. Par défaut il s'agit de la classe Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper. Le code se présente ainsi :

<?xml version="1.0" encoding="UTF-8" ?>
  <container xmlns="http://symfony.com/schema/dic/services"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    <parameters>
      <parameter key="templating.helper.form.class">Frontend\FrontBundle\Helper\FormHelper
    </parameters>
  </container>
La classe surchargée va, avant d'afficher le champ, faire appel à la méthode setTheme(). Tout cela pour déterminer quel thème doit utiliser Symfony2 pour le rendu du formulaire (champ text, boutons radio etc.). Le code de cette FormHelper se présente ainsi :
namespace Frontend\FrontBundle\Helper;

use Symfony\Component\Templating\Helper\Helper;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Exception\FormException;
use Symfony\Component\Form\Util\FormUtil;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper as ParentHelper;

class FormHelper extends ParentHelper
{
    protected $engine;

    protected $varStack;

    protected $context;

    protected $resources;

    protected $themes;

    protected $templates;

    protected function renderSection(FormView $view, $section, array $variables = array())
    {
        // if new theme is set (for exemple for override form templates)
        if(isset($variables['attr']['theme'])) $this->setTheme($view,  $variables['attr']['theme']);
        return parent::renderSection($view, $section, $variables);
    }

}
Afin de personnaliser un champ du formulaire sous Symfony2 il faut passer un paramètre theme qui appelera la fonction setTheme. Voici un exemple :
// it will show the template located ad /app/Resources/views directory
echo $view['form']->widget($form['replyType'], array('attr' => array('theme' => array(0 => ':'))));
Pour voir comment on peut personnaliser ces champs, veuillez vous référer aux fichiers placés dans /vendor/Symfony/Bundle/FrameworkBundle/Resources/views/Form.