diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY
new file mode 100644
index 0000000000000000000000000000000000000000..01505555eb60ae07b0b40fcf263867c5028246bf
--- /dev/null
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY
@@ -0,0 +1 @@
+InnerDetector/InDetValidation/InDetPhysValMonitoring
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h
index 6416676735700e9d4d91b6f45df3c9132b36ddcd..dfadc7d58e6669e138afc149837c3373565caa0f 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h
@@ -36,6 +36,7 @@
 
 //Athena
 #include "AtlasDetDescr/AtlasDetectorID.h"
+#include "CxxUtils/checker_macros.h"
 #include "InDetIdentifier/PixelID.h"
 #include "InDetIdentifier/SCT_ID.h"
 #include "InDetIdentifier/TRT_ID.h"
@@ -138,7 +139,7 @@ private:
     ToolHandle<IInDetVertexTruthMatchTool> m_vtxValidTool;
     ToolHandle<IAthSelectionTool> m_truthSelectionTool;
     mutable std::mutex  m_mutex;
-    mutable CutFlow     m_truthCutFlow;
+    mutable CutFlow     m_truthCutFlow ATLAS_THREAD_SAFE; // Guarded by m_mutex
     std::vector<int> m_prospectsMatched;
     float m_lowProb;
     float m_highProb;
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h
index c648fee859ce2b6b28e4c14f321e2a37f8c8ccaf..1175c1e92976895deba3cda00723309e3a68fd43 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h
@@ -16,6 +16,7 @@
 
 #include "AthenaKernel/MsgStreamMember.h"
 #include "AthenaBaseComps/AthMsgStreamMacros.h"
+#include "CxxUtils/checker_macros.h"
 
 class TH1;
 class TH2;
@@ -157,7 +158,7 @@ namespace IDPVM {
     }
 
     /// Private message stream member
-    mutable Athena::MsgStreamMember m_msg;
+    mutable Athena::MsgStreamMember m_msg ATLAS_THREAD_SAFE;
 
 
   };
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h
index de43273aec9d94b2face80c093098a58e3bcfb2f..b7d68141ceb0755af471c48b6e48b3c683369bcf 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h
@@ -8,6 +8,7 @@
 
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "TrkToolInterfaces/ITrackSlimmingTool.h"
+#include "CxxUtils/checker_macros.h"
 
 class DummyTrackSlimmingTool: virtual public Trk::ITrackSlimmingTool, public AthAlgTool
 {
@@ -35,7 +36,7 @@ public:
      @return A 'slimmed' version of 'track', where exactly what information is copied depends on how the tool is
         configured
    */
-  virtual Trk::Track* slim(const Trk::Track& track) const override;
+  virtual Trk::Track* slim ATLAS_NOT_THREAD_SAFE (const Trk::Track& track) const override;
   virtual std::unique_ptr<Trk::Track> slimCopy(const Trk::Track& track) const override;
   virtual void slimTrack(Trk::Track&) const override;
 
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx
index e991f621e9c875c2f24ada557bd9b702a1753dff..f6c8abdba72a5326f7b737e8b2716097ea0459a8 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx
@@ -55,9 +55,8 @@ InDetPerfPlot_HitEfficiency::fill(const xAOD::TrackParticle& trkprt) {
   }
 
   const bool hitDetailsAvailable = trkprt.isAvailable<std::vector<int> >("measurement_region");
-  static int warnCount(0);
   if (!hitDetailsAvailable) {
-    if (warnCount++ < 10) {
+    if (m_warnCount++ < 10) {
       ATH_MSG_WARNING("The HitEff plots dont see any data (note: only 10 warnings issued)");
     }
   } else {
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h
index b33712b3595f3e1acbfd50ec5024d3469c8afecd..16e78e76b67dc4f9c3046bf315aff122fb5aed19 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h
@@ -22,6 +22,7 @@
 
 
 // std includes
+#include <atomic>
 #include <string>
 
 class TProfile;
@@ -50,6 +51,8 @@ private:
   //TProfile* m_eff_hit_vs_eta[N_SUBDETECTORS][N_REGIONS];
   TEfficiency* m_HitEfficiencyVsEta[N_SUBDETECTORS][N_REGIONS];
   bool m_debug;
+
+  mutable std::atomic<int> m_warnCount{0};
 };
 
 
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx
index bd8197261b65b4d75b145aae43a998ca3a857313..01e9163a65d99b88ec5bb64c8313d284bc23664b 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx
@@ -103,10 +103,9 @@ InDetPerfPlot_HitResidual::initializePlots() {
 void
 InDetPerfPlot_HitResidual::fill(const xAOD::TrackParticle& trkprt) {
   const static bool hitDetailsAvailable = trkprt.isAvailable<std::vector<int> >("measurement_region");
-  static int warnCount(0);
 
   if (!hitDetailsAvailable) {
-    if (warnCount++ < 10) {
+    if (m_warnCount++ < 10) {
       ATH_MSG_WARNING("The hit res plots dont see any data (note:only 10 warnings issued)");
     }
   } else {
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h
index b90f2f738b770c8b222743743ac6044bf637ab0a..9ecc146ec6de10fdf545be11ae46afb53cb1f066 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h
@@ -11,6 +11,7 @@
 
 
 // std includes
+#include <atomic>
 #include <string>
 #include <vector>
 #include "TProfile.h"
@@ -60,6 +61,8 @@ private:
   TH1* m_pully[N_SUBDETECTORS][N_REGIONS];
   TH1* m_phiWidth[N_SUBDETECTORS][N_REGIONS];
   TH1* m_etaWidth[N_SUBDETECTORS][N_REGIONS];
+
+  mutable std::atomic<int> m_warnCount{0};
 };
 
 
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx
index c22fe1a3e2ebdf78caeb9da14a0da4475916f341..e95505f585b0b3e10b106dd9441b8ff45be5acee 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx
@@ -138,7 +138,7 @@ InDetPhysHitDecoratorAlg::decorateTrack(const xAOD::TrackParticle &particle,
                                          std::vector< SG::WriteDecorHandle<xAOD::TrackParticleContainer,std::vector<float> > > &float_decor,
                                          std::vector< SG::WriteDecorHandle<xAOD::TrackParticleContainer,std::vector<int> > > &int_decor) const
 {
-  static int trackNumber(0);
+  int trackNumber(0);
 
   typedef std::tuple<int, int, int, float, float, float, float, int, int, int> SingleResult_t;
   typedef std::vector<SingleResult_t> TrackResult_t;
@@ -424,7 +424,6 @@ const Trk::TrackParameters*
 InDetPhysHitDecoratorAlg::getUnbiasedTrackParameters(const Trk::TrackParameters* trkParameters,
                                                       const Trk::MeasurementBase* measurement,
                                                       bool &isUnbiased) const {
-  static bool alreadyWarned(false);
   const Trk::TrackParameters* unbiasedTrkParameters(trkParameters);
 
   if (!m_updatorHandle.empty() && (isUnbiased)) {
@@ -437,11 +436,11 @@ InDetPhysHitDecoratorAlg::getUnbiasedTrackParameters(const Trk::TrackParameters*
         ATH_MSG_INFO(  "Could not get unbiased track parameters, use normal parameters" );
         isUnbiased = false;
       }
-    } else if (not alreadyWarned) {
+    } else if (not m_alreadyWarned) {
       // warn only once!
       ATH_MSG_WARNING("TrackParameters contain no covariance, unbiased track states can not be calculated "
                       "(ie. pulls and residuals will be too small)" );
-      alreadyWarned = true;
+      m_alreadyWarned = true;
       isUnbiased = false;
     } else {
       isUnbiased = false;
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h
index 14c11c5f2193e8f78106e93eb0ad1b7c972ef8cd..a399d7a7a27d9db40b9fbc66aa56d425cf7dc086 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h
@@ -11,6 +11,7 @@
  * @date 27 March 2014
  **/
 // STL includes
+#include <mutex>
 #include <string>
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
 #include "GaudiKernel/ToolHandle.h"
@@ -88,6 +89,7 @@ private:
 
   const double m_ptThreshold;
   bool m_doUpgrade;
+  mutable std::atomic<bool> m_alreadyWarned{false};
   // the following help identify a surface in the detector
   const AtlasDetectorID* m_idHelper;
   const PixelID* m_pixelID;
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx
index 26ae809920948eb5bab2f728035ea71a20dac15d..678bcdf689dbbc9b9e4e6a7ad61b8ba435c8a3bb 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx
@@ -121,15 +121,14 @@ InDetPhysValTruthDecoratorAlg::decorateTruth(const xAOD::TruthParticle& particle
     return false;
   }
 
-  static bool errorEmitted(false);
   const xAOD::TruthVertex* ptruthVertex(0);
   try{
     ptruthVertex = particle.prodVtx();
   } catch (const std::exception& e) {
-    if (not errorEmitted) {
+    if (not m_errorEmitted) {
       ATH_MSG_WARNING("A non existent production vertex was requested in calculating the track parameters d0 etc");
     }
-    errorEmitted = true;
+    m_errorEmitted = true;
     return false;
   }
   if (!ptruthVertex) {
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h
index e64769abcfb26161cbe5f9578f43dee8b13a0e86..2e07f752ba705c575116b2cb6db84ea8448a0cf4 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef INDETPHYSVALMONITORING_INDETPHYSVALTRUTHDECORATORTOOL_H
@@ -23,6 +23,8 @@
 #include "GaudiKernel/EventContext.h"
 #include "InDetPhysValMonitoring/IAthSelectionTool.h"
 #include "InDetPhysValMonitoring/CutFlow.h"
+#include "CxxUtils/checker_macros.h"
+#include <atomic>
 #include <utility>
 #include <vector>
 
@@ -51,7 +53,9 @@ private:
      {this,"TruthSelectionTool","",""};
 
   mutable std::mutex m_mutex;
-  mutable CutFlow m_cutFlow;
+  mutable CutFlow m_cutFlow ATLAS_THREAD_SAFE; // Guarded by m_mutex
+
+  mutable std::atomic<bool> m_errorEmitted{false};
 
   ///TruthParticle container's name needed to create decorators
   SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleName
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h
index bdc44e8ea9866ec8c9594b5bfa57d339f3fc596c..4e0dbba4850223286b161a7bddde2db4054dda54 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h
@@ -12,6 +12,7 @@
 #include "TrkValHistUtils/PlotBase.h"
 #include "AthenaKernel/MsgStreamMember.h"
 #include "AthenaBaseComps/AthMsgStreamMacros.h"
+#include "CxxUtils/checker_macros.h"
 #include "InDetPhysValMonitoring/SingleHistogramDefinition.h" // to make available to children
 
 #include <string>
@@ -98,7 +99,7 @@ protected:
   }
 
   /// Private message stream member
-  mutable Athena::MsgStreamMember m_msg;
+  mutable Athena::MsgStreamMember m_msg ATLAS_THREAD_SAFE;
 private:
   IHistogramDefinitionSvc* m_histoDefSvc;
 };
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx
index 41d23e837a7c44d46f62f9f113ef60244b0941fe..03d21ec828faacde4ffcf62a16a77cdfb12523b0 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 //
 //  ReadFromXmlDom.cxx
@@ -20,6 +20,19 @@
 #include <cmath>
 #include <regex>
 
+#include "CxxUtils/checker_macros.h"
+ATLAS_NO_CHECK_FILE_THREAD_SAFETY;
+// The following warning message is given if checked:
+// warning: Use of static expression 'xercesc_3_1::XMLPlatformUtils::fgMemoryManager'
+// of type 'xercesc_3_1::MemoryManager*' within function
+// 'toNative(const XMLCh*)::<lambda(char*)>' may not be thread-safe.
+//
+// https://xerces.apache.org/xerces-c/faq-parse-3.html#faq-6
+// Is Xerces-C++ thread-safe?
+// The answer is yes if you observe the following rules for using Xerces-C++
+// in a multi-threaded environment:
+// ... ...
+
 namespace {
   bool
   validAxisName(const std::string& proposedName, const std::array<std::string, 3>& allowedNames) {
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h
index 96d9e0b9406f56c2d88c11e0468f85653c57c27b..bb1a7f53c677093f44fb6553ceabe95b1d84e86a 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 //
 //  ReadFromXmlDom.h
@@ -15,7 +15,18 @@
 #include "InDetPhysValMonitoring/SingleHistogramDefinition.h"
 #include <xercesc/parsers/XercesDOMParser.hpp>
 
-
+#include "CxxUtils/checker_macros.h"
+ATLAS_NO_CHECK_FILE_THREAD_SAFETY;
+// The following warning message is given if checked:
+// warning: Use of static expression 'xercesc_3_1::XMLPlatformUtils::fgMemoryManager'
+// of type 'xercesc_3_1::MemoryManager*' within function
+// 'toNative(const XMLCh*)::<lambda(char*)>' may not be thread-safe.
+//
+// https://xerces.apache.org/xerces-c/faq-parse-3.html#faq-6
+// Is Xerces-C++ thread-safe?
+// The answer is yes if you observe the following rules for using Xerces-C++
+// in a multi-threaded environment:
+// ... ...
 
 class ReadFromXmlDom: public IReadHistoDef {
 public:
@@ -35,4 +46,4 @@ private:
   SingleHistogramDefinition parseTProfileText(const std::string& line);
   SingleHistogramDefinition parseXmlElement(const xercesc::DOMElement* element);
 };
-#endif /* ReadFromXmlDom_h */
\ No newline at end of file
+#endif /* ReadFromXmlDom_h */
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx
index a2e003ff8cf59a643c2fd2e8eb187aecf1fe0188..2caf893d1afbfe749ec9c6316c7a37b028327070 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx
@@ -135,6 +135,7 @@ TrackTruthSelectionTool::accept(const xAOD::TruthParticle* p) const {
   if (m_pdgId > -1) {
     acceptData.setCutResult("pdgId", (std::fabs(p->pdgId()) == m_pdgId));// 3-18-16 normally on, disabled for testing
   }
+  std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numTruthPassedCuts
   // Book keep cuts
   for (const auto& cut : m_cuts) {
     unsigned int pos = acceptData.getCutPosition(cut.first);
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h
index cbb5119fc43ae7e985986ba32848e48f97efe37f..5d534336a6ae83d2b0035e762b95c5732f117ef6 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef INDETPHYSVALMONITORING_TRACKTRUTHSELECTORTOOL_H
@@ -10,6 +10,8 @@
 #include "xAODTruth/TruthParticle.h"
 #include "AsgTools/AsgTool.h"
 
+#include <atomic>
+#include <mutex>
 
 class TrackTruthSelectionTool:
   public virtual ::IAsgSelectionTool,
@@ -29,9 +31,10 @@ public:
 private:
   asg::AcceptInfo m_accept;
   std::vector<std::pair<std::string, std::string> > m_cuts;
-  mutable ULong64_t m_numTruthProcessed; // !< a counter of the number of tracks proccessed
-  mutable ULong64_t m_numTruthPassed; // !< a counter of the number of tracks that passed all cuts
-  mutable std::vector<ULong64_t> m_numTruthPassedCuts; // !< tracks the number of tracks that passed each cut family
+  mutable std::atomic<ULong64_t> m_numTruthProcessed; // !< a counter of the number of tracks proccessed
+  mutable std::atomic<ULong64_t> m_numTruthPassed; // !< a counter of the number of tracks that passed all cuts
+  mutable std::vector<ULong64_t> m_numTruthPassedCuts ATLAS_THREAD_SAFE; // !< tracks the number of tracks that passed each cut family. Guarded by m_mutex
+  mutable std::mutex m_mutex; // !< To guard m_numTruthPassedCuts
 
   // Cut values;
   float m_maxEta;
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx
index 23a22447c35ed9e4c8c60ac1258ce1e499b49f12..ce3e5662fdd5ff7b63f0e1ae93437bbb73d02765 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx
@@ -192,50 +192,52 @@ dRMatchingTool::sortVectors(const T* container,
 
 void
 dRMatchingTool::checkCacheTrackParticles(const xAOD::TrackParticleContainer* trackParticles,
+                                         CacheEntry* ent,
                                          bool (* trackSelectionTool)(const xAOD::TrackParticle*)) const {
   // Check whether to cache.
-  if (*trackParticles == m_baseTrackContainer) {
+  if (*trackParticles == ent->m_baseTrackContainer) {
     return;
   }
 
   // Clear existing cache.
-  clearTrackParticles();
+  clearTrackParticles(ent);
 
   // Cache track particles.
   sortVectors<xAOD::TrackParticleContainer,
               xAOD::TrackParticle>(trackParticles,
-                                   m_trackParticlesSortedPt,
-                                   m_trackParticlesSortedEta,
-                                   m_trackParticlesSortedPhi,
+                                   ent->m_trackParticlesSortedPt,
+                                   ent->m_trackParticlesSortedEta,
+                                   ent->m_trackParticlesSortedPhi,
                                    trackSelectionTool);
 
   // Store copy of base track container.
-  m_baseTrackContainer = *trackParticles;
+  ent->m_baseTrackContainer = *trackParticles;
 
   return;
 }
 
 void
 dRMatchingTool::checkCacheTruthParticles(const xAOD::TruthParticleContainer* truthParticles,
+                                         CacheEntry* ent,
                                          bool (* truthSelectionTool)(const xAOD::TruthParticle*)) const {
   // Check whether to cache.
-  if (*truthParticles == m_baseTruthContainer) {
+  if (*truthParticles == ent->m_baseTruthContainer) {
     return;
   }
 
   // Clear existing cache.
-  clearTruthParticles();
+  clearTruthParticles(ent);
 
   // Cache truth particles.
   sortVectors<xAOD::TruthParticleContainer,
               xAOD::TruthParticle>(truthParticles,
-                                   m_truthParticlesSortedPt,
-                                   m_truthParticlesSortedEta,
-                                   m_truthParticlesSortedPhi,
+                                   ent->m_truthParticlesSortedPt,
+                                   ent->m_truthParticlesSortedEta,
+                                   ent->m_truthParticlesSortedPhi,
                                    truthSelectionTool);
 
   // Store copy of base truth container.
-  m_baseTruthContainer = *truthParticles;
+  ent->m_baseTruthContainer = *truthParticles;
 
   return;
 }
@@ -245,9 +247,10 @@ bool
 dRMatchingTool::sortedMatch(const U* p,
                             std::vector< const V* >& vec_pt,
                             std::vector< const V* >& vec_eta,
-                            std::vector< const V* >& vec_phi) const {
+                            std::vector< const V* >& vec_phi,
+                            float& dRmin) const {
   // (Re-)set variables.
-  m_dRmin = 9999.;
+  dRmin = 9999.;
 
   // Perform search in cached vectors.
   auto it_pt_lower = m_pTResMax < 0 ? vec_pt.begin() :
@@ -363,8 +366,8 @@ dRMatchingTool::sortedMatch(const U* p,
   bool passes = false;
   for (const V* other : set) {
     float dR = comp_deltaR(p, other);
-    m_dRmin = (dR < m_dRmin ? dR : m_dRmin);
-    passes |= m_dRmin < m_dRmax;
+    dRmin = (dR < dRmin ? dR : dRmin);
+    passes |= dRmin < m_dRmax;
   }
 
   return passes;
@@ -376,14 +379,20 @@ dRMatchingTool::accept(const xAOD::TrackParticle* track,
                        bool (* truthSelectionTool)(const xAOD::TruthParticle*)) const {
   asg::AcceptData acceptData (&m_accept);
 
+  std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache
+  const EventContext& ctx{Gaudi::Hive::currentContext()};
+  CacheEntry* ent{m_cache.get(ctx)};
+  ent->check(ctx.evt());
+
   // Determine whether to cache current truth particle container
-  checkCacheTruthParticles(truthParticles, truthSelectionTool);
+  checkCacheTruthParticles(truthParticles, ent, truthSelectionTool);
 
   bool passes = sortedMatch<xAOD::TrackParticle,
                             xAOD::TruthParticle>(track,
-                                                 m_truthParticlesSortedPt,
-                                                 m_truthParticlesSortedEta,
-                                                 m_truthParticlesSortedPhi);
+                                                 ent->m_truthParticlesSortedPt,
+                                                 ent->m_truthParticlesSortedEta,
+                                                 ent->m_truthParticlesSortedPhi,
+                                                 ent->m_dRmin);
 
   // Set cut values.
   if (m_dRmax > -1) {
@@ -415,14 +424,20 @@ dRMatchingTool::accept(const xAOD::TruthParticle* truth,
                        bool (* trackSelectionTool)(const xAOD::TrackParticle*)) const {
   asg::AcceptData acceptData (&m_accept);
 
+  std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache
+  const EventContext& ctx{Gaudi::Hive::currentContext()};
+  CacheEntry* ent{m_cache.get(ctx)};
+  ent->check(ctx.evt());
+
   // Determine whether to cache current track particle container
-  checkCacheTrackParticles(trackParticles, trackSelectionTool);
+  checkCacheTrackParticles(trackParticles, ent, trackSelectionTool);
 
   bool passes = sortedMatch<xAOD::TruthParticle,
                             xAOD::TrackParticle>(truth,
-                                                 m_trackParticlesSortedPt,
-                                                 m_trackParticlesSortedEta,
-                                                 m_trackParticlesSortedPhi);
+                                                 ent->m_trackParticlesSortedPt,
+                                                 ent->m_trackParticlesSortedEta,
+                                                 ent->m_trackParticlesSortedPhi,
+                                                 ent->m_dRmin);
 
   // Set cut values.
   if (m_dRmax > -1) {
@@ -453,7 +468,13 @@ dRMatchingTool::acceptLegacy(const xAOD::TrackParticle* p,
                              const xAOD::TruthParticleContainer* truthParticles,
                              bool (* truthSelectionTool)(const xAOD::TruthParticle*)) const {
   asg::AcceptData acceptData (&m_accept);
-  m_dRmin = 9999.;
+
+  std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache
+  const EventContext& ctx{Gaudi::Hive::currentContext()};
+  CacheEntry* ent{m_cache.get(ctx)};
+  ent->check(ctx.evt());
+
+  ent->m_dRmin = 9999.;
 
   // Define variables.
   const unsigned int Ncuts(m_cuts.size());
@@ -492,7 +513,7 @@ dRMatchingTool::acceptLegacy(const xAOD::TrackParticle* p,
 
     // If the current truth particle was matched, check minimal dR.
     if (passesThis) {
-      m_dRmin = (dR < m_dRmin ? dR : m_dRmin);
+      ent->m_dRmin = (dR < ent->m_dRmin ? dR : ent->m_dRmin);
     }
   }
 
@@ -526,7 +547,13 @@ dRMatchingTool::acceptLegacy(const xAOD::TruthParticle* p,
                              bool (* trackSelectionTool)(const xAOD::TrackParticle*)) const {
   // Reset the results.
   asg::AcceptData acceptData (&m_accept);
-  m_dRmin = 9999.;
+
+  std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache
+  const EventContext& ctx{Gaudi::Hive::currentContext()};
+  CacheEntry* ent{m_cache.get(ctx)};
+  ent->check(ctx.evt());
+
+  ent->m_dRmin = 9999.;
 
   // Define variables.
   const unsigned int Ncuts(m_cuts.size());
@@ -565,7 +592,7 @@ dRMatchingTool::acceptLegacy(const xAOD::TruthParticle* p,
 
     // If the current track particle was matched, check minimal dR.
     if (passesThis) {
-      m_dRmin = (dR < m_dRmin ? dR : m_dRmin);
+      ent->m_dRmin = (dR < ent->m_dRmin ? dR : ent->m_dRmin);
     }
   }
 
@@ -615,5 +642,10 @@ dRMatchingTool::finalize() {
 
 float
 dRMatchingTool::dRmin() const {
-  return m_dRmin;
+  std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_cache
+  const EventContext& ctx{Gaudi::Hive::currentContext()};
+  CacheEntry* ent{m_cache.get(ctx)};
+  ent->check(ctx.evt());
+
+  return ent->m_dRmin;
 }
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h
index b9827c94fcdd486d94ef28d0f5c6b095b86c9965..8cb919089d08b608e17f56235fcea4d10579f4b7 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef INDETPHYSVALMONITORING_DRMATCHINGTOOL_H
@@ -13,12 +13,16 @@
  */
 
 // STL include(s)
+#include <atomic>
 #include <cmath> /* std::fabs, sqrt, pow */
 #include <algorithm> /* std::all_of (C++11), std::sort, std::lower_bound, std::upper_bound, std::set_intersection */
 #include <iterator> /* std::back_inserter */
+#include <mutex>
 
 // ATLAS software include(s)
 #include "AthenaBaseComps/AthAlgTool.h"
+#include "AthenaKernel/SlotSpecificObj.h"
+#include "CxxUtils/checker_macros.h"
 #include "PATCore/IAsgSelectionTool.h"
 #include "AsgTools/AsgTool.h"
 
@@ -121,29 +125,71 @@ public:
   // Accessor for the minimal dR from the latest matching of either type.
   float dRmin() const;
 protected:
+  // Struct for event cache
+  struct CacheEntry {
+    EventContext::ContextEvt_t m_evt{EventContext::INVALID_CONTEXT_EVT};
+
+    // The minimal dR for latest successful matching of either type.
+    float m_dRmin = 9999.;
+
+    // Copy of the xAOD::TruthParticleContainer used to perform the caching. A
+    // copy, rather than a pointer or reference, is necessary to check when a new
+    // container is encountered (i.e. when a new event is processed).
+    xAOD::TruthParticleContainer m_baseTruthContainer;
+    // Copy of the xAOD::TrackParticleContainer used to perform the caching.
+    xAOD::TrackParticleContainer m_baseTrackContainer;
+
+    // Cached vectors of the xAOD::TruthParticles in m_baseTruthContainer, sorted
+    // in ascending order accoring to their pT, eta, and phi, resp.
+    std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPt;
+    std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedEta;
+    std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPhi;
+    // Cached vectors of the xAOD::TrackParticles in m_baseTrackContainer, sorted
+    // in ascending order accoring to their pT, eta, and phi, resp.
+    std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPt;
+    std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedEta;
+    std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPhi;
+
+    void check(EventContext::ContextEvt_t evt) {
+      // Check event number and reset variables if a new event
+      if (m_evt==evt) return;
+
+      m_dRmin = 9999.;
+      m_truthParticlesSortedPt.clear();
+      m_truthParticlesSortedEta.clear();
+      m_truthParticlesSortedPhi.clear();
+      m_trackParticlesSortedPt.clear();
+      m_trackParticlesSortedEta.clear();
+      m_trackParticlesSortedPhi.clear();
+      m_evt = evt;
+    }
+  };
+
   /// Internal method(s).
   // Cache track particles.
   void checkCacheTrackParticles(const xAOD::TrackParticleContainer* trackParticles,
+                                CacheEntry* ent,
                                 bool (* trackSelectionTool)(const xAOD::TrackParticle*) = nullptr) const;
   // Cache truth particles.
   void checkCacheTruthParticles(const xAOD::TruthParticleContainer* truthParticles,
+                                CacheEntry* ent,
                                 bool (* truthSelectionTool)(const xAOD::TruthParticle*) = nullptr) const;
 
   // Clear cached track particle arrays.
   inline void
-  clearTrackParticles() const {
-    m_trackParticlesSortedPt.clear();
-    m_trackParticlesSortedEta.clear();
-    m_trackParticlesSortedPhi.clear();
+  clearTrackParticles(CacheEntry* ent) const {
+    ent->m_trackParticlesSortedPt.clear();
+    ent->m_trackParticlesSortedEta.clear();
+    ent->m_trackParticlesSortedPhi.clear();
     return;
   }
 
   // Clear cached truth particle arrays.
   inline void
-  clearTruthParticles() const {
-    m_truthParticlesSortedPt.clear();
-    m_truthParticlesSortedEta.clear();
-    m_truthParticlesSortedPhi.clear();
+  clearTruthParticles(CacheEntry* ent) const {
+    ent->m_truthParticlesSortedPt.clear();
+    ent->m_truthParticlesSortedEta.clear();
+    ent->m_truthParticlesSortedPhi.clear();
     return;
   }
 
@@ -162,7 +208,8 @@ protected:
   bool sortedMatch(const U* p,
                    std::vector< const V* >& vec_pt,
                    std::vector< const V* >& vec_eta,
-                   std::vector< const V* >& vec_phi) const;
+                   std::vector< const V* >& vec_phi,
+                   float& dRmin) const;
 private:
   /// Data member(s).
   // AcceptInfo object.
@@ -171,35 +218,19 @@ private:
   std::vector<std::pair<std::string, std::string> > m_cuts;
 
   // Counters.
-  mutable ULong64_t m_numProcessed; // !< a counter of the number of tracks proccessed
-  mutable ULong64_t m_numPassed; // !< a counter of the number of tracks that passed all cuts
-  mutable std::vector<ULong64_t> m_numPassedCuts; // !< tracks the number of tracks that passed each cut family
+  mutable std::atomic<ULong64_t> m_numProcessed; // !< a counter of the number of tracks proccessed
+  mutable std::atomic<ULong64_t> m_numPassed; // !< a counter of the number of tracks that passed all cuts
+  mutable std::vector<ULong64_t> m_numPassedCuts ATLAS_THREAD_SAFE; // !< tracks the number of tracks that passed each cut family. Guarded by m_mutex
+  mutable std::mutex m_mutex; // !< To guard m_numPassedCuts and m_cache
 
   /// Cut vales.
   // The maximal dR-distance allowed for successful matching.
   float m_dRmax;
   // The maximal pT-resolution allowed for successful matching.
   float m_pTResMax;
-  // The minimal dR for latest successful matching of either type.
-  mutable float m_dRmin = 9999.;
-
-  // Copy of the xAOD::TruthParticleContainer used to perform the caching. A
-  // copy, rather than a pointer or reference, is necessary to check when a new
-  // container is encountered (i.e. when a new event is processed).
-  mutable xAOD::TruthParticleContainer m_baseTruthContainer;
-  // Copy of the xAOD::TrackParticleContainer used to perform the caching.
-  mutable xAOD::TrackParticleContainer m_baseTrackContainer;
-
-  // Cached vectors of the xAOD::TruthParticles in m_baseTruthContainer, sorted
-  // in ascending order accoring to their pT, eta, and phi, resp.
-  mutable std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPt;
-  mutable std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedEta;
-  mutable std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPhi;
-  // Cached vectors of the xAOD::TrackParticles in m_baseTrackContainer, sorted
-  // in ascending order accoring to their pT, eta, and phi, resp.
-  mutable std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPt;
-  mutable std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedEta;
-  mutable std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPhi;
+
+  // Event cache
+  mutable SG::SlotSpecificObj<CacheEntry> m_cache ATLAS_THREAD_SAFE; // Guarded by m_mutex
 };
 
 #endif // > !INDETPHYSVALMONITORING_DRMATCHINGTOOL_H
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h
index 1236432ded767903933389e7177185a91d83f98b..409ddac07fbda4f14b9566dd7468076bbd985077 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 //
 //  xmlUtilities.h
@@ -16,7 +16,18 @@
 #include <xercesc/util/XMLString.hpp>           // transcode
 #include <xercesc/dom/DOM.hpp>                  // DOMxxx
 
-
+#include "CxxUtils/checker_macros.h"
+ATLAS_NO_CHECK_FILE_THREAD_SAFETY;
+// The following warning message is given if checked:
+// warning: Use of static expression 'xercesc_3_1::XMLPlatformUtils::fgMemoryManager'
+// of type 'xercesc_3_1::MemoryManager*' within function
+// 'toNative(const XMLCh*)::<lambda(char*)>' may not be thread-safe.
+//
+// https://xerces.apache.org/xerces-c/faq-parse-3.html#faq-6
+// Is Xerces-C++ thread-safe?
+// The answer is yes if you observe the following rules for using Xerces-C++
+// in a multi-threaded environment:
+// ... ...
 
 typedef std::basic_string<XMLCh>XercesString;
 inline XercesString
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx
index d9e716903366b96719cc691c055d11f5661ed289..a1f099bf11024a67969d7598b23a94228306f970 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx
@@ -23,6 +23,10 @@
 #include "../InDetPhysValMonitoring/SingleHistogramDefinition.h"
 #include <utility> //std::pair
 
+#include "CxxUtils/checker_macros.h"
+ATLAS_NO_CHECK_FILE_THREAD_SAFETY;
+// This test uses global svcLoc and hDefSvc, and is not thread safe.
+
 static const std::string testJobOptionsFile("IDPVM_Test.txt");
 
 struct GaudiKernelFixture:public IDPVM_GaudiFixtureBase{
@@ -109,4 +113,4 @@ BOOST_AUTO_TEST_SUITE(HistogramDefinitionSvcTest)
   }
 BOOST_AUTO_TEST_SUITE_END()
 
-  
\ No newline at end of file
+  
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h
index 4b8296fe0acd689a620a28d76e681dec19eae5d5..31e77d8f716e4611cdee284a77bdbc695178edda 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h
@@ -19,6 +19,10 @@
 #include "CxxUtils/ubsan_suppress.h"
 #include <string>
 
+#include "CxxUtils/checker_macros.h"
+ATLAS_NO_CHECK_FILE_THREAD_SAFETY;
+// This test uses static gaudiIsInitialised, and is not thread safe.
+
 struct IDPVM_GaudiFixtureBase{
   ISvcLocator* svcLoc{};
   static bool gaudiIsInitialised;
diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx
index d02e10db624b89cbca060e7396455d50cb2361a6..107e534d81d2f084827102ca132f04c01cd5ed7b 100644
--- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx
+++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx
@@ -23,6 +23,10 @@
 #include "../InDetPhysValMonitoring/SingleHistogramDefinition.h"
 #include <utility> //std::pair
 
+#include "CxxUtils/checker_macros.h"
+ATLAS_NO_CHECK_FILE_THREAD_SAFETY;
+// This test uses global svcLoc and hDefSvc, and is not thread safe.
+
 static const std::string entityInclusionOptions("XmlEntityInclusionOptions.txt");
 /*
   The job options refer to an xml file 'entityMaster.xml' which contains