Avoid unnecessary volatile reads
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientH2PrefaceHandler.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientH2PrefaceHandler.java
index 9730b3a..41d3800 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientH2PrefaceHandler.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientH2PrefaceHandler.java
@@ -104,7 +104,10 @@
         ioSession.setEvent(SelectionKey.OP_WRITE);
     }
 
-    private void writeOutPreface(final IOSession session) throws IOException  {
+    /**
+     * @return true if the entire preface has been written out
+     */
+    private boolean writeOutPreface(final IOSession session, final ByteBuffer preface) throws IOException  {
         if (preface.hasRemaining()) {
             session.write(preface);
         }
@@ -115,8 +118,9 @@
             if (inBuf != null) {
                 inBuf.clear();
             }
-            preface = null;
+            return true;
         }
+        return false;
     }
 
     @Override
@@ -131,8 +135,11 @@
         if (initialized.compareAndSet(false, true)) {
             initialize();
         }
+        final ByteBuffer preface = this.preface;
         if (preface != null) {
-            writeOutPreface(session);
+            if (writeOutPreface(session, preface)) {
+                this.preface = null;
+            }
         } else {
             throw new ProtocolNegotiationException("Unexpected output");
         }
@@ -146,8 +153,11 @@
             }
             inBuf.put(src);
         }
+        final ByteBuffer preface = this.preface;
         if (preface != null) {
-            writeOutPreface(session);
+            if (writeOutPreface(session, preface)) {
+                this.preface = null;
+            }
         } else {
             throw new ProtocolNegotiationException("Unexpected input");
         }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/AbstractCharDataConsumer.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/AbstractCharDataConsumer.java
index efd7a44..d89104a 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/AbstractCharDataConsumer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/AbstractCharDataConsumer.java
@@ -111,6 +111,7 @@
     }
 
     private CharsetDecoder getCharsetDecoder() {
+        CharsetDecoder charsetDecoder = this.charsetDecoder;
         if (charsetDecoder == null) {
             Charset charset = this.charset;
             if (charset == null) {
@@ -120,6 +121,7 @@
                 charset = StandardCharsets.UTF_8;
             }
             charsetDecoder = charset.newDecoder();
+            this.charsetDecoder = charsetDecoder;
             if (charCodingConfig.getMalformedInputAction() != null) {
                 charsetDecoder.onMalformedInput(charCodingConfig.getMalformedInputAction());
             }
@@ -134,6 +136,7 @@
     public final void consume(final ByteBuffer src) throws IOException {
         final CharsetDecoder charsetDecoder = getCharsetDecoder();
         while (src.hasRemaining()) {
+            ByteBuffer byteBuffer = this.byteBuffer;
             if (byteBuffer != null && byteBuffer.position() > 0) {
                 // There are some left-overs from the previous input operation
                 final int n = byteBuffer.remaining();
@@ -159,6 +162,7 @@
                     // in case of input underflow src can be expected to be very small (one incomplete UTF8 char)
                     if (byteBuffer == null) {
                         byteBuffer = ByteBuffer.allocate(Math.max(src.remaining(), 1024));
+                        this.byteBuffer = byteBuffer;
                     }
                     byteBuffer.put(src);
                 }