10
votes

Primitives de concurrence dans Scala

Quels seraient de bonnes primitives en concurrence pour accéder à un objet lié à la CPU (sans IO et réseautage)?

Par exemple, il y a un FOOCOUNTER, qui a une méthode GET (), SET () et INC () pour Var Counter: Int, qui soit partagé entre des milliers et des millions de threads. P>

object FooCounter{
  var counter: Int = 0;
  def get() = counter
  def set(value: Int) = {counter = counter + value} 
  def inc() = counter + 1
}


2 commentaires

Je n'ai pas vraiment eu le temps pour une réponse complète, mais vous avez raison que Akka n'est pas vraiment la bonne chose pour cela. Jetez un coup d'œil à nBonson.github.io/scala-stm - Il implémente la mémoire transactionnelle logicielle , qui fonctionne précisément pour ce scénario. Je pense que cela va être ajouté à la bibliothèque standard Scala.


"Des millions de threads" ... Bien sûr


6 Réponses :


4
votes

Vous pouvez utiliser toutes les primitives de syntonisation Java, telles que AtomicInteger, par exemple pour compter.

Pour des tâches plus compliquées, j'ai personnellement comme Scala-STM Bibliothèque: http://nbronson.github.io/scala-stm/

avec STM Votre exemple ressemblera à ceci xxx

Cependant, pour cet exemple simple, je m'arrêterais sur les primitives Java.


2 commentaires

D'accord, je peux utiliser des primitives Java, mais mon objectif est d'utiliser des API Scala et apprenez-les. Merci d'avoir répondu.


BTW serait-il un bon choix de faire du comptoir immuable et de la définir avec un modèle CopyOnwrite?



3
votes

Vous avez raison sur l'orientation "Akka" à Scala: dans l'ensemble, je pense qu'il y a un joli chevauchement de la communauté des développeurs de langue Scala et d'Akka. Les versions tardives de Scala s'appuient sur des acteurs Akka pour la concurrence, mais franchement, je ne peux pas voir une anithidification mauvaise dans cette situation.

En ce qui concerne votre question, Citez "Akka in Action" Book:

Les acteurs sont parfaits pour traiter de nombreux messages, capturant l'état et réagir avec différents comportements basés sur les messages qu'ils reçoivent "

et

"Les futures sont l'outil à utiliser lorsque vous préférez utiliser des fonctions et N'ayez pas vraiment besoin d'objets pour faire le travail "

Un avenir est un espace réservé pour une valeur non encore disponible, alors même s'il est utilisé pour des tâches non bloquantes, c'est utile pour plus de cela et je pense que cela pourrait être votre choix ici.


2 commentaires

J'ai besoin de regarder Akka plus précisément. Ma compréhension de Akka est d'encombrer au cluster Akka, itinéraires pour cette tâche simple. Pourriez-vous s'il vous plaît élaborer comment l'avenir peut protéger ma valeur contre des milliers de threads?


Vous n'avez pas besoin de regrouper ou de routage si vous utilisez simplement des tâches simultanées dans le même JVM. C'est pourquoi akka-cluster et AKKA-REMOTING sont des dépendances distinctes de la bibliothèque CORE AKKA-acteur .



2
votes

Une des solutions possibles de votre tâche est des acteurs. Ce n'est pas la solution la plus rapide mais sûre et simple: xxx


0 commentaires

3
votes

Si vous n'êtes pas disposé à utiliser java.util.concurrent code> directement, votre solution la plus élégante peut utiliser AGENTS AKKA .

import java.util.concurrent.atomic.AtomicInteger

class FooCounter {
  val counter = new AtomicInteger(0)
  def get() = counter.get()
  def set(v: Int) = counter.set(v)
  def inc() = counter.incrementAndGet()
  def modify(f: Int => Int) = {
    var done = false
    var oldVal: Int = 0
    while (!done) {
      oldVal = counter.get()
      done = counter.compareAndSet(oldVal, f(oldVal))
    }
  }
}


1 commentaires

Les agents des FYI sont obsolètes



11
votes

Vous devez savoir que votre implémentation de FOOCOUNTER n'est pas du thread-Safe. Si plusieurs threads invoquent simultanément le get , définir et inc méthodes, il n'y a aucune garantie que le compte sera précis. Vous devez utiliser l'un des utilitaires suivants pour mettre en place un compteur concomitable correct:

  • Synchronisée instruction (SCALA Synchronisée est similaire à la un en Java )
  • Variables atomiques
  • STMS (par exemple, scalastm )
  • potentiellement, vous pouvez utiliser un acteur AKKA qui est un comptoir, mais noter que ce n'est pas l'application la plus simple des acteurs

    Autres utilitaires de concurrence Scala, tels que contrats à terme et promesses, collections parallèles ou extensions réactives, ne sont pas le mieux adapté à la mise en œuvre d'un compteur simultané et ont des usages différents.

    Vous devez savoir que Scala dans certains cas réutilise l'infrastructure de simultanéité Java. Par exemple, Scala ne fournit pas de variables atomiques à part, car les classes Atomiques Java font déjà le travail. Au lieu de cela, SCALA a pour objectif de fournir des abstractions de concurrence de niveau supérieur, telles que des acteurs, des STMS et des flux d'événements asynchrones.

    Benchmarking

    Pour évaluer l'heure et l'efficacité de votre implémentation de votre implémentation, un bon choix est scalamètre . La documentation en ligne sur le site Web contient des exemples détaillés sur la manière de faire des analyses d'analyse comparative.

    Documentation et bibliothèques de concurrence

    Pendant que AKKA est l'utilitaire de simultanécence scala le plus populaire et le plus documenté, il existe de nombreuses autres implémentations de haute qualité, dont certaines sont plus appropriées pour différentes tâches:


1 commentaires

Merci d'avoir répondu. J'ai déjà pré-commandé un livre. Au plaisir de lire quand il serait disponible.



0
votes

java.util.concurrent.atomic.atomicinteger fonctionne très bien avec Scala, fait compter le threadsafe, et vous n'avez pas à mettre des dépendances supplémentaires dans votre projet.


0 commentaires