diff --git a/Framework/MDAlgorithms/src/MDNormSCD.cpp b/Framework/MDAlgorithms/src/MDNormSCD.cpp
index 866d15d23ab3ebe6334938397390247274069f09..ed8155a2690f7f1acf8d728d4c875647ba9fc7e6 100644
--- a/Framework/MDAlgorithms/src/MDNormSCD.cpp
+++ b/Framework/MDAlgorithms/src/MDNormSCD.cpp
@@ -363,6 +363,16 @@ void MDNormSCD::cacheDimensionXValues() {
   }
 }
 
+namespace {
+template <typename T, typename BinaryOp>
+void AtomicOp(std::atomic<T> &f, T d, BinaryOp _Op) {
+  T old = f.load();
+  T desired = _Op(old, d);
+  while (!f.compare_exchange_weak(old, desired))
+    desired = _Op(old, d);
+}
+} // namespace
+
 /**
  * Computed the normalization for the input workspace. Results are stored in
  * m_normWS
@@ -402,6 +412,8 @@ void MDNormSCD::calculateNormalization(
   const detid2index_map solidAngDetToIdx =
       solidAngleWS->getDetectorIDToWorkspaceIndexMap();
 
+  std::vector<std::atomic<signal_t>> signalArray(m_normWS->getNPoints());
+
   auto prog = make_unique<API::Progress>(this, 0.3, 1.0, ndets);
   PARALLEL_FOR_IF(Kernel::threadSafe(*integrFlux))
   for (int64_t i = 0; i < ndets; i++) {
@@ -474,18 +486,16 @@ void MDNormSCD::calculateNormalization(
       // index of the current intersection
       size_t k = static_cast<size_t>(std::distance(intersectionsBegin, it));
       // signal = integral between two consecutive intersections
-      double signal = (yValues[k] - yValues[k - 1]) * solid;
-
-      PARALLEL_CRITICAL(updateMD) {
-        signal += m_normWS->getSignalAt(linIndex);
-        m_normWS->setSignalAt(linIndex, signal);
-      }
+      signal_t signal = (yValues[k] - yValues[k - 1]) * solid;
+      AtomicOp(signalArray[linIndex], signal, std::plus<signal_t>());
     }
     prog->report();
 
     PARALLEL_END_INTERUPT_REGION
   }
   PARALLEL_CHECK_INTERUPT_REGION
+  std::copy(signalArray.cbegin(), signalArray.cend(),
+            m_normWS->getSignalArray());
 }
 
 /**