Funktionale Möglichkeit, einen threadsicheren gemeinsamen Zähler zu implementieren

Ich bin relativ neu in Scala und der funktionalen Programmierung und mag die Idee, dass ich mit unveränderlichen Objekten viele Sicherheitsrisiken für Threads vermeiden kann. Eine Sache verfolgt mich immer noch, und es ist das klassische Beispiel, das zum Lehren der Thread-Sicherheit verwendet wird - der gemeinsame Zähler.

Ich habe mich gefragt, ob es möglich ist, einen thread-sicheren Zähler (in diesem Beispiel einen Anforderungszähler) mit unveränderlichen Objekten und funktionalen Konzepten zu implementieren und die Synchronisation vollständig zu vermeiden.

Als Referenz hier sind also zuerst die klassischen veränderlichen Versionen des Zählers (entschuldigen Sie die öffentliche Mitgliedsvariable, nur zur Kürze der Beispiele).

Veränderbare, nicht gewindesichere Version:

public class Servlet extends HttpServlet {

  public int requestCount = 0; 

  @Override
  public void service(ServletRequest req, ServletResponse res) throws ... {
    requestCount++; //thread unsafe
    super.service(req, res);  
  }
}

Veränderbare, klassische gewindesichere Version: (oder so hoffe ich ...)

public class Servlet extends HttpServlet {

  public volatile int requestCount = 0;

  @Override
  public void service(ServletRequest req, ServletResponse res) throws ... {
    synchronized (this) {
      requestCount++;
    }
    super.service(req, res);  
  }
}

Ich habe mich gefragt, ob es eine Möglichkeit gibt, unveränderliche Objekte und flüchtige Variablen zu verwenden, um die Thread-Sicherheit ohne Synchronisation zu erreichen.

Also hier war mein naiver Versuch. Die Idee ist, ein unveränderliches Objekt für den Zähler zu haben und nur die Referenz darauf mit einer flüchtigen Variablen zu ersetzen. Fühlt sich fischig an, ist aber einen Versuch wert.

Halter:

public class Incrementer {
  private final int value;
  public Incrementer(final int oldValue) {
    this.value = oldValue + 1;
  }

  public Incrementer() {
    this.value = 0;
  }

  public int getValue() {
    return value;
  }
}

Geändertes Servlet:

public class Servlet extends HttpServlet {

  public volatile Incrementer incrementer = new Incrementer();

  @Override
  public void service(ServletRequest req, ServletResponse res) throws ... {
    incrementer = new Incrementer(incrementer.getValue());
    super.service(req, res);
  }
}

Ich habe das starke Gefühl, dass dies auch nicht threadsicher ist, da ich vom Inkrementierer lese und möglicherweise einen veralteten Wert erhalte (z. B. wenn die Referenz bereits durch einen anderen Thread ersetzt wurde). Falls es in der Tat nicht threadsicher ist, frage ich mich, ob es überhaupt eine "funktionierende" Möglichkeit gibt, mit einem solchen Counter-Szenario ohne Sperren / Synchronisieren umzugehen.

Also meine Frage (n) sind

Ist dieser Thread zufällig sicher?Wenn ja warumWenn nein, gibt es überhaupt eine Möglichkeit, einen solchen Zähler ohne Synchronisation zu implementieren?

Obwohl der obige Beispielcode in Java ist, sind Antworten in Scala natürlich auch willkommen

Antworten auf die Frage(2)

Ihre Antwort auf die Frage