Java – function method of thread safe shared counter

I am new to scala and functional programming. I like the idea of using immutable objects. I can avoid many thread safety traps One thing still bothers me. This is a classic example for teaching thread safety - shared counters

I wonder if I can implement thread - safe counters (request counters in this example), use immutable object and function concepts, and completely avoid synchronization

So the first reference here is the classic variable version of the counter (please forgive me for my public member variable, just for a concise example)

Variable, non thread safe 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);  
  }
}

Variable, classic thread safe version: (or I want...)

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);  
  }
}

I wonder if there is a way to use immutable objects and volatile variables to achieve thread safety without synchronization

So this is my naive attempt Our idea is to provide an immutable object for the counter and replace the reference to it with a volatile variable It feels fishy, but it's worth trying

Holder:

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;
  }
}

Modified 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);
  }
}

I have a strong feeling that this is not thread safe either, because I read from the Delta and may get an old value (for example, if the reference has been replaced by another thread) If it's really not thread safe, I wonder if there is any "functional" way to deal with this counter scenario without locking / synchronization

So my question is

>Is this thread safe? > If so, why? > If not, is there any way to implement such counters without synchronization?

Although the above example code is written in Java, the replies in scala are certainly welcome

Solution

No, this is not thread safe unless you have created immutable objects in the synchronization block It is possible to create a corrupted immutable object under thread contention

To achieve the same functionality, you can use atomicinteger to avoid explicit synchronization

public class Servlet extends HttpServlet {

  public AtomicInteger incrementer = new AtomicInteger (0);

  @Override
  public void service(ServletRequest req,ServletResponse res) throws ... {
    int newValue = incrementer.incrementAndGet();
    super.service(req,res);
  }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>