ICU-20520 UMutex refactoring.

  - Use STATIC_NEW for mutex creation, to avoid order-of-destruction problems
    by avoiding destruction altogether, while avoiding memory leak reports.

  - Remove UConditionVar, replace with direct use of std::condition_variable
diff --git a/icu4c/source/common/brkeng.cpp b/icu4c/source/common/brkeng.cpp
index 19467dc..80e1158 100644
--- a/icu4c/source/common/brkeng.cpp
+++ b/icu4c/source/common/brkeng.cpp
@@ -129,8 +129,8 @@
     const LanguageBreakEngine *lbe = NULL;
     UErrorCode  status = U_ZERO_ERROR;
 
-    static UMutex gBreakEngineMutex = U_MUTEX_INITIALIZER;
-    Mutex m(&gBreakEngineMutex);
+    static UMutex *gBreakEngineMutex = STATIC_NEW(UMutex);
+    Mutex m(gBreakEngineMutex);
 
     if (fEngines == NULL) {
         UStack  *engines = new UStack(_deleteEngine, NULL, status);
diff --git a/icu4c/source/common/characterproperties.cpp b/icu4c/source/common/characterproperties.cpp
index 030cca9..5ce8cac 100644
--- a/icu4c/source/common/characterproperties.cpp
+++ b/icu4c/source/common/characterproperties.cpp
@@ -48,8 +48,8 @@
 UCPMap *maps[UCHAR_INT_LIMIT - UCHAR_INT_START] = {};
 
 icu::UMutex *cpMutex() {
-    static icu::UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static icu::UMutex *m = STATIC_NEW(icu::UMutex);
+    return m;
 }
 
 //----------------------------------------------------------------
diff --git a/icu4c/source/common/cmemory.h b/icu4c/source/common/cmemory.h
index f19715c..814e39d 100644
--- a/icu4c/source/common/cmemory.h
+++ b/icu4c/source/common/cmemory.h
@@ -98,6 +98,23 @@
 #define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
 
 /**
+ * Create & return an instance of "type" in statically allocated storage.
+ * e.g.
+ *    static std::mutex *myMutex = STATIC_NEW(std::mutex);
+ * This is intended for use when
+ *   - We want a static (or global) object.
+ *   - We don't want it to ever be destructed, to avoid order-of-destruction
+ *     or use-after-destruction problems.
+ *   - We want to avoid an ordinary heap allocated object, to avoid triggering
+ *     memory leak reports, from valgrind, for example.
+ * This is defined as a macro rather than a template function because each invocation
+ * must define distinct static storage for the object being returned.
+ */
+#define STATIC_NEW(type) [] () { \
+    alignas(type) static char storage[sizeof(type)]; \
+    return new(storage) type();} ();
+
+/**
   *  Heap clean up function, called from u_cleanup()
   *    Clears any user heap functions from u_setMemoryFunctions()
   *    Does NOT deallocate any remaining allocated memory.
diff --git a/icu4c/source/common/locdspnm.cpp b/icu4c/source/common/locdspnm.cpp
index da35be9..70b0776 100644
--- a/icu4c/source/common/locdspnm.cpp
+++ b/icu4c/source/common/locdspnm.cpp
@@ -549,8 +549,8 @@
     if ( result.length() > 0 && u_islower(result.char32At(0)) && capitalizationBrkIter!= NULL &&
           ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || fCapitalization[usage] ) ) {
         // note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE
-        static UMutex capitalizationBrkIterLock = U_MUTEX_INITIALIZER;
-        Mutex lock(&capitalizationBrkIterLock);
+        static UMutex *capitalizationBrkIterLock = STATIC_NEW(UMutex);
+        Mutex lock(capitalizationBrkIterLock);
         result.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
     }
 #endif
diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp
index 06986b6..eecebf4 100644
--- a/icu4c/source/common/locid.cpp
+++ b/icu4c/source/common/locid.cpp
@@ -38,19 +38,19 @@
 #include "unicode/strenum.h"
 #include "unicode/stringpiece.h"
 #include "unicode/uloc.h"
-#include "putilimp.h"
-#include "mutex.h"
-#include "umutex.h"
-#include "uassert.h"
+
+#include "bytesinkutil.h"
+#include "charstr.h"
 #include "cmemory.h"
 #include "cstring.h"
+#include "mutex.h"
+#include "putilimp.h"
 #include "uassert.h"
+#include "ucln_cmn.h"
 #include "uhash.h"
 #include "ulocimp.h"
-#include "ucln_cmn.h"
+#include "umutex.h"
 #include "ustr_imp.h"
-#include "charstr.h"
-#include "bytesinkutil.h"
 
 U_CDECL_BEGIN
 static UBool U_CALLCONV locale_cleanup(void);
@@ -63,8 +63,8 @@
 
 // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale.
 static UMutex *gDefaultLocaleMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 static UHashtable *gDefaultLocalesHashT = NULL;
 static Locale *gDefaultLocale = NULL;
diff --git a/icu4c/source/common/mutex.h b/icu4c/source/common/mutex.h
index 47f5e08..55768fb 100644
--- a/icu4c/source/common/mutex.h
+++ b/icu4c/source/common/mutex.h
@@ -28,50 +28,51 @@
 
 U_NAMESPACE_BEGIN
 
-//----------------------------------------------------------------------------
-// Code within that accesses shared static or global data should
-// should instantiate a Mutex object while doing so. You should make your own 
-// private mutex where possible.
-
-// For example:
-//
-// UMutex myMutex = U_MUTEX_INITIALIZER;
-//
-// void Function(int arg1, int arg2)
-// {
-//    static Object* foo;     // Shared read-write object
-//    Mutex mutex(&myMutex);  // or no args for the global lock
-//    foo->Method();
-//    // When 'mutex' goes out of scope and gets destroyed here, the lock is released
-// }
-//
-// Note:  Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function
-//        returning a Mutex. This is a common mistake which silently slips through the
-//        compiler!!
-//
+/**
+  * Mutex is a helper class for convenient locking and unlocking of a UMutex.
+  *
+  * Creating a local scope Mutex will lock a UMutex, holding the lock until the Mutex
+  * goes out of scope.
+  *
+  *  If no UMutex is specified, the ICU global mutex is implied.
+  *
+  *  For example:
+  *
+  *  UMutex *myMutex() {
+  *    static UMutex *m = STATIC_NEW(UMutex);
+  *    return m;
+  *  }
+  *
+  *  void Function(int arg1, int arg2)
+  *  {
+  *     static Object* foo;      // Shared read-write object
+  *     Mutex mutex(myMutex());  // or no args for the global lock
+  *     foo->Method();
+  *     // When 'mutex' goes out of scope and gets destroyed here, the lock is released
+  *  }
+  *
+  *  Note:  Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function
+  *         returning a Mutex. This is a common mistake which silently slips through the
+  *         compiler!!
+  */
 
 class U_COMMON_API Mutex : public UMemory {
 public:
-  inline Mutex(UMutex *mutex = NULL);
-  inline ~Mutex();
+    Mutex(UMutex *mutex = nullptr) : fMutex(mutex) {
+        umtx_lock(fMutex);
+    };
+    ~Mutex() {
+        umtx_unlock(fMutex);
+    };
+
+    Mutex(const Mutex &other) = delete; // forbid assigning of this class
+    Mutex &operator=(const Mutex &other) = delete; // forbid copying of this class
+    void *operator new(size_t s) = delete;  // forbid heap allocation. Locals only.
 
 private:
-  UMutex   *fMutex;
-
-  Mutex(const Mutex &other); // forbid copying of this class
-  Mutex &operator=(const Mutex &other); // forbid copying of this class
+    UMutex   *fMutex;
 };
 
-inline Mutex::Mutex(UMutex *mutex)
-  : fMutex(mutex)
-{
-  umtx_lock(fMutex);
-}
-
-inline Mutex::~Mutex()
-{
-  umtx_unlock(fMutex);
-}
 
 U_NAMESPACE_END
 
diff --git a/icu4c/source/common/putil.cpp b/icu4c/source/common/putil.cpp
index 289a8aa..2f9f2bb 100644
--- a/icu4c/source/common/putil.cpp
+++ b/icu4c/source/common/putil.cpp
@@ -249,8 +249,8 @@
 }
 
 static UDate getUTCtime_fake() {
-    static UMutex fakeClockMutex = U_MUTEX_INTIALIZER;
-    umtx_lock(&fakeClockMutex);
+    static UMutex *fakeClockMutex = STATIC_NEW(UMutex);
+    umtx_lock(fakeClockMutex);
     if(!fakeClock_set) {
         UDate real = getUTCtime_real();
         const char *fake_start = getenv("U_FAKETIME_START");
@@ -267,7 +267,7 @@
         }
         fakeClock_set = TRUE;
     }
-    umtx_unlock(&fakeClockMutex);
+    umtx_unlock(fakeClockMutex);
 
     return getUTCtime_real() + fakeClock_dt;
 }
diff --git a/icu4c/source/common/resbund.cpp b/icu4c/source/common/resbund.cpp
index 08cda3a..4d4909c 100644
--- a/icu4c/source/common/resbund.cpp
+++ b/icu4c/source/common/resbund.cpp
@@ -51,6 +51,7 @@
 #include "unicode/utypes.h"
 #include "unicode/resbund.h"
 
+#include "cmemory.h"
 #include "mutex.h"
 #include "uassert.h"
 #include "umutex.h"
@@ -377,8 +378,8 @@
 }
 
 const Locale &ResourceBundle::getLocale(void) const {
-    static UMutex gLocaleLock = U_MUTEX_INITIALIZER;
-    Mutex lock(&gLocaleLock);
+    static UMutex *gLocaleLock = STATIC_NEW(UMutex);
+    Mutex lock(gLocaleLock);
     if (fLocale != NULL) {
         return *fLocale;
     }
diff --git a/icu4c/source/common/serv.cpp b/icu4c/source/common/serv.cpp
index 555c055..b92e4e4 100644
--- a/icu4c/source/common/serv.cpp
+++ b/icu4c/source/common/serv.cpp
@@ -334,8 +334,8 @@
 */
 
 static UMutex *lock() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 ICUService::ICUService()
diff --git a/icu4c/source/common/servls.cpp b/icu4c/source/common/servls.cpp
index 90874d1..1af6b4a 100644
--- a/icu4c/source/common/servls.cpp
+++ b/icu4c/source/common/servls.cpp
@@ -263,9 +263,9 @@
 {
     const Locale&     loc    = Locale::getDefault();
     ICULocaleService* ncThis = (ICULocaleService*)this;
-    static UMutex llock = U_MUTEX_INITIALIZER;
+    static UMutex *llock = STATIC_NEW(UMutex);
     {
-        Mutex mutex(&llock);
+        Mutex mutex(llock);
         if (loc != fallbackLocale) {
             ncThis->fallbackLocale = loc;
             LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
diff --git a/icu4c/source/common/servnotf.cpp b/icu4c/source/common/servnotf.cpp
index 1e65a14..e7a7ca5 100644
--- a/icu4c/source/common/servnotf.cpp
+++ b/icu4c/source/common/servnotf.cpp
@@ -22,8 +22,8 @@
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener)
 
 static UMutex *notifyLock() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 ICUNotifier::ICUNotifier(void) 
diff --git a/icu4c/source/common/ucnv_bld.cpp b/icu4c/source/common/ucnv_bld.cpp
index b71be8f..42ddbd3 100644
--- a/icu4c/source/common/ucnv_bld.cpp
+++ b/icu4c/source/common/ucnv_bld.cpp
@@ -195,8 +195,8 @@
 /*initializes some global variables */
 static UHashtable *SHARED_DATA_HASHTABLE = NULL;
 static icu::UMutex *cnvCacheMutex() {                 /* Mutex for synchronizing cnv cache access. */
-    static icu::UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static icu::UMutex *m = STATIC_NEW(icu::UMutex);
+    return m;
 }
 /*  Note:  the global mutex is used for      */
 /*         reference count updates.          */
diff --git a/icu4c/source/common/ucurr.cpp b/icu4c/source/common/ucurr.cpp
index 444adc0..105b11d 100644
--- a/icu4c/source/common/ucurr.cpp
+++ b/icu4c/source/common/ucurr.cpp
@@ -366,8 +366,8 @@
 struct CReg;
 
 static UMutex *gCRegLock() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 static CReg* gCRegHead = 0;
 
@@ -1357,8 +1357,8 @@
 static int8_t currentCacheEntryIndex = 0;
 
 static UMutex *gCurrencyCacheMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 // Cache deletion
diff --git a/icu4c/source/common/udata.cpp b/icu4c/source/common/udata.cpp
index efcd2a2..853a32f 100644
--- a/icu4c/source/common/udata.cpp
+++ b/icu4c/source/common/udata.cpp
@@ -831,8 +831,8 @@
      * Use a specific mutex to avoid nested locks of the global mutex.
      */
 #if MAP_IMPLEMENTATION==MAP_STDIO
-    static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER;
-    umtx_lock(&extendICUDataMutex);
+    static UMutex *extendICUDataMutex = STATIC_NEW(UMutex);
+    umtx_lock(extendICUDataMutex);
 #endif
     if(!umtx_loadAcquire(gHaveTriedToLoadCommonData)) {
         /* See if we can explicitly open a .dat file for the ICUData. */
@@ -868,7 +868,7 @@
                                                           /* Also handles a race through here before gHaveTriedToLoadCommonData is set. */
 
 #if MAP_IMPLEMENTATION==MAP_STDIO
-    umtx_unlock(&extendICUDataMutex);
+    umtx_unlock(extendICUDataMutex);
 #endif
     return didUpdate;               /* Return true if ICUData pointer was updated.   */
                                     /*   (Could potentially have been done by another thread racing */
diff --git a/icu4c/source/common/umutex.cpp b/icu4c/source/common/umutex.cpp
index 20b03d6..774071e 100644
--- a/icu4c/source/common/umutex.cpp
+++ b/icu4c/source/common/umutex.cpp
@@ -43,8 +43,8 @@
 
 // The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer.
 static UMutex *globalMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 U_CAPI void  U_EXPORT2
@@ -65,32 +65,6 @@
     mutex->fMutex.unlock();
 }
 
-UConditionVar::UConditionVar() : fCV() {
-}
-
-UConditionVar::~UConditionVar() {
-}
-
-U_CAPI void U_EXPORT2
-umtx_condWait(UConditionVar *cond, UMutex *mutex) {
-    if (mutex == nullptr) {
-        mutex = globalMutex();
-    }
-    cond->fCV.wait(mutex->fMutex);
-}
-
-
-U_CAPI void U_EXPORT2
-umtx_condBroadcast(UConditionVar *cond) {
-    cond->fCV.notify_all();
-}
-
-
-U_CAPI void U_EXPORT2
-umtx_condSignal(UConditionVar *cond) {
-    cond->fCV.notify_one();
-}
-
 
 /*************************************************************************************************
  *
@@ -99,13 +73,13 @@
  *************************************************************************************************/
 
 static std::mutex &initMutex() {
-    static std::mutex m;
-    return m;
+    static std::mutex *m = STATIC_NEW(std::mutex);
+    return *m;
 }
 
 static std::condition_variable &initCondition() {
-    static std::condition_variable cv;
-    return cv;
+    static std::condition_variable *cv = STATIC_NEW(std::condition_variable);
+    return *cv;
 }
 
 
diff --git a/icu4c/source/common/umutex.h b/icu4c/source/common/umutex.h
index d0a7e7a..476fcef 100755
--- a/icu4c/source/common/umutex.h
+++ b/icu4c/source/common/umutex.h
@@ -181,13 +181,24 @@
 }
 
 
-/*************************************************************************************************
- *
+/**
  * ICU Mutex wrappers.  Originally wrapped operating system mutexes, giving the rest of ICU a
  * platform independent set of mutex operations.  Now vestigial, wrapping std::mutex only.
  * For internal ICU use only.
  *
- *************************************************************************************************/
+ * Caution: do not directly declare static or global instances of UMutex. Doing so can introduce
+ * static initializers, which are disallowed in ICU library code. Instead, use the following
+ * idiom, which avoids static init and also avoids ordering issues on destruction
+ * (use after delete) by avoiding destruction altogether.
+ *
+ *  UMutex *myMutex() {
+ *      static UMutex *m = STATIC_NEW(UMutex);
+ *      return m;
+ *  }
+ *  ...
+ *
+ *  Mutex lock(myMutex());   // hold myMutex until the variable "lock" goes out of scope.
+ */
 
 struct UMutex : public icu::UMemory {
     UMutex() = default;
@@ -199,31 +210,6 @@
     //                           //       plain C style functions (umtx_lock(), etc.)
 };
 
-
-struct UConditionVar : public icu::UMemory {
-	U_COMMON_API UConditionVar();
-	U_COMMON_API ~UConditionVar();
-    UConditionVar(const UConditionVar &other) = delete;
-    UConditionVar &operator =(const UConditionVar &other) = delete;
-
-    std::condition_variable_any fCV;
-};
-
-#define U_MUTEX_INITIALIZER {}
-#define U_CONDITION_INITIALIZER {}
-
-// Implementation notes for UConditionVar:
-//
-// Use an out-of-line constructor to reduce problems with the ICU dependency checker.
-// On Linux, the default constructor of std::condition_variable_any
-// produces an in-line reference to global operator new(), which the
-// dependency checker flags for any file that declares a UConditionVar. With
-// an out-of-line constructor, the dependency is constrained to umutex.o
-//
-// Do not export (U_COMMON_API) the entire class, but only the constructor
-// and destructor, to avoid Windows build problems with attempting to export the
-// std::condition_variable_any.
-
 /* Lock a mutex.
  * @param mutex The given mutex to be locked.  Pass NULL to specify
  *              the global ICU mutex.  Recursive locks are an error
@@ -237,30 +223,6 @@
  */
 U_INTERNAL void U_EXPORT2 umtx_unlock (UMutex* mutex);
 
-/*
- * Wait on a condition variable.
- * The calling thread will unlock the mutex and wait on the condition variable.
- * The mutex must be locked by the calling thread when invoking this function.
- *
- * @param cond the condition variable to wait on.
- * @param mutex the associated mutex.
- */
-
-U_INTERNAL void U_EXPORT2 umtx_condWait(UConditionVar *cond, UMutex *mutex);
-
-
-/*
- * Broadcast wakeup of all threads waiting on a Condition.
- *
- * @param cond the condition variable.
- */
-U_INTERNAL void U_EXPORT2 umtx_condBroadcast(UConditionVar *cond);
-
-/*
- * Signal a condition variable, waking up one waiting thread.
- */
-U_INTERNAL void U_EXPORT2 umtx_condSignal(UConditionVar *cond);
-
 
 U_NAMESPACE_END
 
diff --git a/icu4c/source/common/unifiedcache.cpp b/icu4c/source/common/unifiedcache.cpp
index 641f4ec..ed7cf57 100644
--- a/icu4c/source/common/unifiedcache.cpp
+++ b/icu4c/source/common/unifiedcache.cpp
@@ -13,21 +13,20 @@
 #include "unifiedcache.h"
 
 #include <algorithm>      // For std::max()
+#include <mutex>
 
-#include "mutex.h"
 #include "uassert.h"
 #include "uhash.h"
 #include "ucln_cmn.h"
-#include "umutex.h"
 
 static icu::UnifiedCache *gCache = NULL;
-static icu::UMutex *gCacheMutex() {
-    static icu::UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+static std::mutex &gCacheMutex() {
+    static std::mutex *m = STATIC_NEW(std::mutex);
+    return *m;
 }
-static icu::UConditionVar *gInProgressValueAddedCond() {
-    static icu::UConditionVar cv = U_CONDITION_INITIALIZER;
-    return &cv;
+static std::condition_variable &gInProgressValueAddedCond() {
+    static std::condition_variable *cv = STATIC_NEW(std::condition_variable);
+    return *cv;
 }
 static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
 
@@ -138,28 +137,28 @@
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return;
     }
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
     fMaxUnused = count;
     fMaxPercentageOfInUse = percentageOfInUseItems;
 }
 
 int32_t UnifiedCache::unusedCount() const {
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
     return uhash_count(fHashtable) - fNumValuesInUse;
 }
 
 int64_t UnifiedCache::autoEvictedCount() const {
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
     return fAutoEvictedCount;
 }
 
 int32_t UnifiedCache::keyCount() const {
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
     return uhash_count(fHashtable);
 }
 
 void UnifiedCache::flush() const {
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
 
     // Use a loop in case cache items that are flushed held hard references to
     // other cache items making those additional cache items eligible for
@@ -168,7 +167,7 @@
 }
 
 void UnifiedCache::handleUnreferencedObject() const {
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
     --fNumValuesInUse;
     _runEvictionSlice();
 }
@@ -187,7 +186,7 @@
 }
 
 void UnifiedCache::dumpContents() const {
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
     _dumpContents();
 }
 
@@ -227,7 +226,7 @@
         // Now all that should be left in the cache are entries that refer to
         // each other and entries with hard references from outside the cache.
         // Nothing we can do about these so proceed to wipe out the cache.
-        Mutex lock(gCacheMutex());
+        std::lock_guard<std::mutex> lock(gCacheMutex());
         _flush(TRUE);
     }
     uhash_close(fHashtable);
@@ -328,7 +327,7 @@
         const CacheKeyBase &key,
         const SharedObject *&value,
         UErrorCode &status) const {
-    Mutex lock(gCacheMutex());
+    std::lock_guard<std::mutex> lock(gCacheMutex());
     const UHashElement *element = uhash_find(fHashtable, &key);
     if (element != NULL && !_inProgress(element)) {
         _fetch(element, value, status);
@@ -353,15 +352,15 @@
         UErrorCode &status) const {
     U_ASSERT(value == NULL);
     U_ASSERT(status == U_ZERO_ERROR);
-    Mutex lock(gCacheMutex());
+    std::unique_lock<std::mutex> lock(gCacheMutex());
     const UHashElement *element = uhash_find(fHashtable, &key);
 
     // If the hash table contains an inProgress placeholder entry for this key,
     // this means that another thread is currently constructing the value object.
     // Loop, waiting for that construction to complete.
      while (element != NULL && _inProgress(element)) {
-        umtx_condWait(gInProgressValueAddedCond(), gCacheMutex());
-        element = uhash_find(fHashtable, &key);
+         gInProgressValueAddedCond().wait(lock);
+         element = uhash_find(fHashtable, &key);
     }
 
     // If the hash table contains an entry for the key,
@@ -433,7 +432,7 @@
 
     // Tell waiting threads that we replace in-progress status with
     // an error.
-    umtx_condBroadcast(gInProgressValueAddedCond());
+    gInProgressValueAddedCond().notify_all();
 }
 
 void UnifiedCache::_fetch(
diff --git a/icu4c/source/common/uresbund.cpp b/icu4c/source/common/uresbund.cpp
index 483f5ff..7f99211 100644
--- a/icu4c/source/common/uresbund.cpp
+++ b/icu4c/source/common/uresbund.cpp
@@ -50,8 +50,8 @@
 static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
 
 static UMutex *resbMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 /* INTERNAL: hashes an entry  */
diff --git a/icu4c/source/common/usprep.cpp b/icu4c/source/common/usprep.cpp
index eb2b2a1..5d72cc7 100644
--- a/icu4c/source/common/usprep.cpp
+++ b/icu4c/source/common/usprep.cpp
@@ -48,8 +48,8 @@
 static icu::UInitOnce gSharedDataInitOnce = U_INITONCE_INITIALIZER;
 
 static UMutex *usprepMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 /* format version of spp file */
diff --git a/icu4c/source/i18n/astro.cpp b/icu4c/source/i18n/astro.cpp
index e6dcfe8..d2973d3 100644
--- a/icu4c/source/i18n/astro.cpp
+++ b/icu4c/source/i18n/astro.cpp
@@ -66,8 +66,8 @@
 }
 
 static icu::UMutex *ccLock() {
-    static icu::UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static icu::UMutex *m = STATIC_NEW(icu::UMutex);
+    return m;
 }
 
 U_CDECL_BEGIN
diff --git a/icu4c/source/i18n/chnsecal.cpp b/icu4c/source/i18n/chnsecal.cpp
index 2472870..f6a687e 100644
--- a/icu4c/source/i18n/chnsecal.cpp
+++ b/icu4c/source/i18n/chnsecal.cpp
@@ -52,8 +52,8 @@
 
 // --- The cache --
 static icu::UMutex *astroLock() {  // Protects access to gChineseCalendarAstro.
-    static icu::UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static icu::UMutex *m = STATIC_NEW(icu::UMutex);
+    return m;
 }
 static icu::CalendarAstronomer *gChineseCalendarAstro = NULL;
 
diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp
index 42cf5c5..93105e0 100644
--- a/icu4c/source/i18n/dtfmtsym.cpp
+++ b/icu4c/source/i18n/dtfmtsym.cpp
@@ -1246,9 +1246,9 @@
 DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
 {
     const UnicodeString **result = NULL;
-    static UMutex LOCK = U_MUTEX_INITIALIZER;
+    static UMutex *LOCK = STATIC_NEW(UMutex);
 
-    umtx_lock(&LOCK);
+    umtx_lock(LOCK);
     if (fZoneStrings == NULL) {
         if (fLocaleZoneStrings == NULL) {
             ((DateFormatSymbols*)this)->initZoneStringsArray();
@@ -1259,7 +1259,7 @@
     }
     rowCount = fZoneStringsRowCount;
     columnCount = fZoneStringsColCount;
-    umtx_unlock(&LOCK);
+    umtx_unlock(LOCK);
 
     return result;
 }
diff --git a/icu4c/source/i18n/dtitvfmt.cpp b/icu4c/source/i18n/dtitvfmt.cpp
index 0e124f5..0976dd5 100644
--- a/icu4c/source/i18n/dtitvfmt.cpp
+++ b/icu4c/source/i18n/dtitvfmt.cpp
@@ -83,8 +83,8 @@
 //        Needed because these data members are modified by const methods of DateIntervalFormat.
 
 static UMutex *gFormatterMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 DateIntervalFormat* U_EXPORT2
diff --git a/icu4c/source/i18n/gender.cpp b/icu4c/source/i18n/gender.cpp
index 50161e1..b57f009 100644
--- a/icu4c/source/i18n/gender.cpp
+++ b/icu4c/source/i18n/gender.cpp
@@ -98,11 +98,11 @@
     return NULL;
   }
 
-  static UMutex gGenderMetaLock = U_MUTEX_INITIALIZER;
+  static UMutex *gGenderMetaLock = STATIC_NEW(UMutex);
   const GenderInfo* result = NULL;
   const char* key = locale.getName();
   {
-    Mutex lock(&gGenderMetaLock);
+    Mutex lock(gGenderMetaLock);
     result = (const GenderInfo*) uhash_get(gGenderInfoCache, key);
   }
   if (result) {
@@ -118,7 +118,7 @@
   // Try to put our GenderInfo object in cache. If there is a race condition,
   // favor the GenderInfo object that is already in the cache.
   {
-    Mutex lock(&gGenderMetaLock);
+    Mutex lock(gGenderMetaLock);
     GenderInfo* temp = (GenderInfo*) uhash_get(gGenderInfoCache, key);
     if (temp) {
       result = temp;
diff --git a/icu4c/source/i18n/islamcal.cpp b/icu4c/source/i18n/islamcal.cpp
index a024f4c..b44b60c 100644
--- a/icu4c/source/i18n/islamcal.cpp
+++ b/icu4c/source/i18n/islamcal.cpp
@@ -470,8 +470,8 @@
 {
     double age = 0;
 
-    static UMutex astroLock = U_MUTEX_INITIALIZER;      // pod bay door lock
-    umtx_lock(&astroLock);
+    static UMutex *astroLock = STATIC_NEW(UMutex);      // pod bay door lock
+    umtx_lock(astroLock);
     if(gIslamicCalendarAstro == NULL) {
         gIslamicCalendarAstro = new CalendarAstronomer();
         if (gIslamicCalendarAstro == NULL) {
@@ -482,7 +482,7 @@
     }
     gIslamicCalendarAstro->setTime(time);
     age = gIslamicCalendarAstro->getMoonAge();
-    umtx_unlock(&astroLock);
+    umtx_unlock(astroLock);
 
     // Convert to degrees and normalize...
     age = age * 180 / CalendarAstronomer::PI;
diff --git a/icu4c/source/i18n/listformatter.cpp b/icu4c/source/i18n/listformatter.cpp
index 802ab0e..0260546 100644
--- a/icu4c/source/i18n/listformatter.cpp
+++ b/icu4c/source/i18n/listformatter.cpp
@@ -144,9 +144,9 @@
     keyBuffer.append(':', errorCode).append(style, errorCode);
     UnicodeString key(keyBuffer.data(), -1, US_INV);
     ListFormatInternal* result = nullptr;
-    static UMutex listFormatterMutex = U_MUTEX_INITIALIZER;
+    static UMutex *listFormatterMutex = STATIC_NEW(UMutex);
     {
-        Mutex m(&listFormatterMutex);
+        Mutex m(listFormatterMutex);
         if (listPatternHash == nullptr) {
             initializeHash(errorCode);
             if (U_FAILURE(errorCode)) {
@@ -164,7 +164,7 @@
     }
 
     {
-        Mutex m(&listFormatterMutex);
+        Mutex m(listFormatterMutex);
         ListFormatInternal* temp = static_cast<ListFormatInternal*>(listPatternHash->get(key));
         if (temp != nullptr) {
             delete result;
diff --git a/icu4c/source/i18n/measfmt.cpp b/icu4c/source/i18n/measfmt.cpp
index 0b2ba8f..cb51038 100644
--- a/icu4c/source/i18n/measfmt.cpp
+++ b/icu4c/source/i18n/measfmt.cpp
@@ -801,10 +801,10 @@
     // #13606: DateFormat is not thread-safe, but MeasureFormat advertises itself as thread-safe.
     FieldPosition smallestFieldPosition(smallestField);
     UnicodeString draft;
-    static UMutex dateFmtMutex = U_MUTEX_INITIALIZER;
-    umtx_lock(&dateFmtMutex);
+    static UMutex *dateFmtMutex = STATIC_NEW(UMutex);
+    umtx_lock(dateFmtMutex);
     dateFmt.format(date, draft, smallestFieldPosition, status);
-    umtx_unlock(&dateFmtMutex);
+    umtx_unlock(dateFmtMutex);
 
     // If we find field for smallest amount replace it with the formatted
     // smallest amount from above taking care to replace the integer part
diff --git a/icu4c/source/i18n/numfmt.cpp b/icu4c/source/i18n/numfmt.cpp
index 7adf902..d0c96b6 100644
--- a/icu4c/source/i18n/numfmt.cpp
+++ b/icu4c/source/i18n/numfmt.cpp
@@ -1362,8 +1362,8 @@
         // TODO: Bad hash key usage, see ticket #8504.
         int32_t hashKey = desiredLocale.hashCode();
 
-        static icu::UMutex nscacheMutex = U_MUTEX_INITIALIZER;
-        Mutex lock(&nscacheMutex);
+        static UMutex *nscacheMutex = STATIC_NEW(UMutex);
+        Mutex lock(nscacheMutex);
         ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey);
         if (ns == NULL) {
             ns = NumberingSystem::createInstance(desiredLocale,status);
diff --git a/icu4c/source/i18n/rbt.cpp b/icu4c/source/i18n/rbt.cpp
index b440793..d56d46b 100644
--- a/icu4c/source/i18n/rbt.cpp
+++ b/icu4c/source/i18n/rbt.cpp
@@ -253,14 +253,14 @@
     //
     // TODO(andy): Need a better scheme for handling this.
 
-    static UMutex transliteratorDataMutex = U_MUTEX_INITIALIZER;
+    static UMutex *transliteratorDataMutex = STATIC_NEW(UMutex);
     UBool needToLock;
     {
         Mutex m;
         needToLock = (&text != gLockedText);
     }
     if (needToLock) {
-        umtx_lock(&transliteratorDataMutex);  // Contention, longish waits possible here.
+        umtx_lock(transliteratorDataMutex);  // Contention, longish waits possible here.
         Mutex m;
         gLockedText = &text;
         lockedMutexAtThisLevel = TRUE;
@@ -279,7 +279,7 @@
             Mutex m;
             gLockedText = NULL;
         }
-        umtx_unlock(&transliteratorDataMutex);
+        umtx_unlock(transliteratorDataMutex);
     }
 }
 
diff --git a/icu4c/source/i18n/rbtz.cpp b/icu4c/source/i18n/rbtz.cpp
index 4aa143c..d950831 100644
--- a/icu4c/source/i18n/rbtz.cpp
+++ b/icu4c/source/i18n/rbtz.cpp
@@ -149,16 +149,16 @@
 
 void
 RuleBasedTimeZone::completeConst(UErrorCode& status) const {
-    static UMutex gLock = U_MUTEX_INITIALIZER;
+    static UMutex *gLock = STATIC_NEW(UMutex);
     if (U_FAILURE(status)) {
         return;
     }
-    umtx_lock(&gLock);
+    umtx_lock(gLock);
     if (!fUpToDate) {
         RuleBasedTimeZone *ncThis = const_cast<RuleBasedTimeZone*>(this);
         ncThis->complete(status);
     }
-    umtx_unlock(&gLock);
+    umtx_unlock(gLock);
 }
 
 void
diff --git a/icu4c/source/i18n/reldatefmt.cpp b/icu4c/source/i18n/reldatefmt.cpp
index fd54bf0..59732cd 100644
--- a/icu4c/source/i18n/reldatefmt.cpp
+++ b/icu4c/source/i18n/reldatefmt.cpp
@@ -1184,8 +1184,8 @@
 
     // Must guarantee that one thread at a time accesses the shared break
     // iterator.
-    static icu::UMutex gBrkIterMutex = U_MUTEX_INITIALIZER;
-    Mutex lock(&gBrkIterMutex);
+    static UMutex *gBrkIterMutex = STATIC_NEW(UMutex);
+    Mutex lock(gBrkIterMutex);
     str.toTitle(
             fOptBreakIterator->get(),
             fLocale,
diff --git a/icu4c/source/i18n/simpletz.cpp b/icu4c/source/i18n/simpletz.cpp
index cacfa18..9321fda 100644
--- a/icu4c/source/i18n/simpletz.cpp
+++ b/icu4c/source/i18n/simpletz.cpp
@@ -33,6 +33,7 @@
 #include "unicode/gregocal.h"
 #include "unicode/smpdtfmt.h"
 
+#include "cmemory.h"
 #include "gregoimp.h"
 #include "umutex.h"
 
@@ -1083,13 +1084,13 @@
     if (U_FAILURE(status)) {
         return;
     }
-    static UMutex gLock = U_MUTEX_INITIALIZER;
-    umtx_lock(&gLock);
+    static UMutex *gLock = STATIC_NEW(UMutex);
+    umtx_lock(gLock);
     if (!transitionRulesInitialized) {
         SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this);
         ncThis->initTransitionRules(status);
     }
-    umtx_unlock(&gLock);
+    umtx_unlock(gLock);
 }
 
 void
diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp
index e67c453..5e6f40b 100644
--- a/icu4c/source/i18n/smpdtfmt.cpp
+++ b/icu4c/source/i18n/smpdtfmt.cpp
@@ -231,8 +231,8 @@
 static const int32_t HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000;
 
 static UMutex *LOCK() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
diff --git a/icu4c/source/i18n/translit.cpp b/icu4c/source/i18n/translit.cpp
index 7d9c719..9f92bb3 100644
--- a/icu4c/source/i18n/translit.cpp
+++ b/icu4c/source/i18n/translit.cpp
@@ -92,8 +92,8 @@
  * The mutex controlling access to registry object.
  */
 static icu::UMutex *registryMutex() {
-    static icu::UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static icu::UMutex *m = STATIC_NEW(icu::UMutex);
+    return m;
 }
 
 /**
diff --git a/icu4c/source/i18n/tridpars.cpp b/icu4c/source/i18n/tridpars.cpp
index f54393b..fd9bcfc 100644
--- a/icu4c/source/i18n/tridpars.cpp
+++ b/icu4c/source/i18n/tridpars.cpp
@@ -51,8 +51,8 @@
  * The mutex controlling access to SPECIAL_INVERSES
  */
 static UMutex *LOCK() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 TransliteratorIDParser::Specs::Specs(const UnicodeString& s, const UnicodeString& t,
diff --git a/icu4c/source/i18n/tzfmt.cpp b/icu4c/source/i18n/tzfmt.cpp
index cfde4ac..22c5ab2 100644
--- a/icu4c/source/i18n/tzfmt.cpp
+++ b/icu4c/source/i18n/tzfmt.cpp
@@ -151,8 +151,8 @@
 static icu::UInitOnce gShortZoneIdTrieInitOnce = U_INITONCE_INITIALIZER;
 
 static UMutex *gLock() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 U_CDECL_BEGIN
diff --git a/icu4c/source/i18n/tzgnames.cpp b/icu4c/source/i18n/tzgnames.cpp
index 8c0d4a2..5a92a65 100644
--- a/icu4c/source/i18n/tzgnames.cpp
+++ b/icu4c/source/i18n/tzgnames.cpp
@@ -273,8 +273,8 @@
 }
 
 static UMutex *gLock() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 class TZGNCore : public UMemory {
@@ -1122,8 +1122,8 @@
 
 // TZGNCore object cache handling
 static UMutex *gTZGNLock() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 static UHashtable *gTZGNCoreCache = NULL;
 static UBool gTZGNCoreCacheInitialized = FALSE;
diff --git a/icu4c/source/i18n/tznames.cpp b/icu4c/source/i18n/tznames.cpp
index acd6aec..bceab39 100644
--- a/icu4c/source/i18n/tznames.cpp
+++ b/icu4c/source/i18n/tznames.cpp
@@ -30,8 +30,8 @@
 
 // TimeZoneNames object cache handling
 static UMutex *gTimeZoneNamesLock() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 static UHashtable *gTimeZoneNamesCache = NULL;
 static UBool gTimeZoneNamesCacheInitialized = FALSE;
diff --git a/icu4c/source/i18n/tznames_impl.cpp b/icu4c/source/i18n/tznames_impl.cpp
index 51d3e17..09bf12e 100644
--- a/icu4c/source/i18n/tznames_impl.cpp
+++ b/icu4c/source/i18n/tznames_impl.cpp
@@ -53,8 +53,8 @@
 static const int32_t TZDBNAMES_KEYS_SIZE = UPRV_LENGTHOF(TZDBNAMES_KEYS);
 
 static UMutex *gDataMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
 
 static UHashtable* gTZDBNamesMap = NULL;
@@ -391,9 +391,9 @@
         //       Don't do unless it's really required.
 
         // Mutex for protecting the lazy creation of the Trie node structure on the first call to search().
-        static UMutex TextTrieMutex = U_MUTEX_INITIALIZER;
+        static UMutex *TextTrieMutex = STATIC_NEW(UMutex);
 
-        Mutex lock(&TextTrieMutex);
+        Mutex lock(TextTrieMutex);
         if (fLazyContents != NULL) {
             TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
             nonConstThis->buildTrie(status);
@@ -2253,8 +2253,8 @@
     U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
     mzIDKey[mzID.length()] = 0;
 
-    static UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER;
-    umtx_lock(&gTZDBNamesMapLock);
+    static UMutex *gTZDBNamesMapLock = STATIC_NEW(UMutex);
+    umtx_lock(gTZDBNamesMapLock);
     {
         void *cacheVal = uhash_get(gTZDBNamesMap, mzIDKey);
         if (cacheVal == NULL) {
@@ -2297,7 +2297,7 @@
             tzdbNames = (TZDBNames *)cacheVal;
         }
     }
-    umtx_unlock(&gTZDBNamesMapLock);
+    umtx_unlock(gTZDBNamesMapLock);
 
     return tzdbNames;
 }
diff --git a/icu4c/source/i18n/zonemeta.cpp b/icu4c/source/i18n/zonemeta.cpp
index 0e3ee89..cc53ef9 100644
--- a/icu4c/source/i18n/zonemeta.cpp
+++ b/icu4c/source/i18n/zonemeta.cpp
@@ -31,8 +31,8 @@
 #include "uinvchar.h"
 
 static icu::UMutex *gZoneMetaLock() {
-    static icu::UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static icu::UMutex *m = STATIC_NEW(icu::UMutex);
+    return m;
 }
 
 // CLDR Canonical ID mapping table
diff --git a/icu4c/source/io/locbund.cpp b/icu4c/source/io/locbund.cpp
index c4ef195..4b6fe34 100644
--- a/icu4c/source/io/locbund.cpp
+++ b/icu4c/source/io/locbund.cpp
@@ -47,8 +47,8 @@
 
 static inline UNumberFormat * copyInvariantFormatter(ULocaleBundle *result, UNumberFormatStyle style) {
     U_NAMESPACE_USE
-    static UMutex gLock = U_MUTEX_INITIALIZER;
-    Mutex lock(&gLock);
+    static UMutex *gLock = STATIC_NEW(UMutex);
+    Mutex lock(gLock);
     if (result->fNumberFormat[style-1] == NULL) {
         if (gPosixNumberFormat[style-1] == NULL) {
             UErrorCode status = U_ZERO_ERROR;
diff --git a/icu4c/source/test/depstest/dependencies.txt b/icu4c/source/test/depstest/dependencies.txt
index f7404a0..a0f75a6 100644
--- a/icu4c/source/test/depstest/dependencies.txt
+++ b/icu4c/source/test/depstest/dependencies.txt
@@ -20,7 +20,7 @@
     c_strings c_string_formatting
     int_functions floating_point trigonometry
     stdlib_qsort
-    pthread system_locale
+    system_locale
     stdio_input stdio_output file_io readlink_function dir_io mmap_functions dlfcn
     # C++
     cplusplus iostream
@@ -82,10 +82,6 @@
 group: stdlib_qsort
     qsort
 
-group: pthread
-    pthread_mutex_init pthread_mutex_destroy pthread_mutex_lock pthread_mutex_unlock
-    pthread_cond_wait pthread_cond_broadcast pthread_cond_signal
-
 group: system_locale
     getenv
     nl_langinfo setlocale newlocale freelocale
@@ -831,7 +827,7 @@
     # The "platform" group has no ICU dependencies.
     PIC system_misc system_debug malloc_functions ubsan
     c_strings c_string_formatting
-    floating_point pthread system_locale
+    floating_point system_locale
     stdio_input readlink_function dir_io
     dlfcn  # Move related code into icuplug.c?
     cplusplus
diff --git a/icu4c/source/test/depstest/depstest.py b/icu4c/source/test/depstest/depstest.py
index 4d05f06..d83937d 100755
--- a/icu4c/source/test/depstest/depstest.py
+++ b/icu4c/source/test/depstest/depstest.py
@@ -105,10 +105,9 @@
 # in a limited (not transitive) context.  List of (file_name, symbol)
 # TODO: Move this data to dependencies.txt?
 allowed_errors = (
-  ("common/umutex.o", "operator new(unsigned long)"),
-  ("common/umutex.o", "std::__throw_bad_alloc()"),
   ("common/umutex.o", "std::__throw_system_error(int)"),
   ("common/umutex.o", "std::uncaught_exception()"),
+  ("common/unifiedcache.o", "std::__throw_system_error(int)"),
 )
 
 def _Resolve(name, parents):
diff --git a/icu4c/source/test/intltest/intltest.cpp b/icu4c/source/test/intltest/intltest.cpp
index 201c546..c1b6e5b 100644
--- a/icu4c/source/test/intltest/intltest.cpp
+++ b/icu4c/source/test/intltest/intltest.cpp
@@ -1116,8 +1116,8 @@
     // All error messages generated by tests funnel through here.
     // Multithreaded tests can concurrently generate errors, requiring synchronization
     // to keep each message together.
-    static UMutex messageMutex = U_MUTEX_INITIALIZER;
-    Mutex lock(&messageMutex);
+    static UMutex *messageMutex = STATIC_NEW(UMutex);
+    Mutex lock(messageMutex);
 
     // string that starts with a LineFeed character and continues
     // with spaces according to the current indentation
diff --git a/icu4c/source/test/intltest/tsmthred.cpp b/icu4c/source/test/intltest/tsmthred.cpp
index 2c7528f..2f92526 100644
--- a/icu4c/source/test/intltest/tsmthred.cpp
+++ b/icu4c/source/test/intltest/tsmthred.cpp
@@ -241,12 +241,12 @@
 //
 //----------------------------------------------------------------------
 static UMutex *gTestMutexA() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
-static UConditionVar *gThreadsCountChanged() {
-    static UConditionVar cv = U_CONDITION_INITIALIZER;
-    return &cv;
+static std::condition_variable *gThreadsCountChanged() {
+    static std::condition_variable *cv = STATIC_NEW(std::condition_variable);
+    return cv;
 }
 
 static int     gThreadsStarted = 0;
@@ -262,35 +262,34 @@
         // This is the code that each of the spawned threads runs.
         // All threads move together throught the started - middle - done sequence together,
         // waiting for all other threads to reach each point before advancing.
-        umtx_lock(gTestMutexA());
+        std::unique_lock<std::mutex> lock(gTestMutexA()->fMutex);
         gThreadsStarted += 1;
-        umtx_condBroadcast(gThreadsCountChanged());
+        gThreadsCountChanged()->notify_all();
         while (gThreadsStarted < TESTMUTEX_THREAD_COUNT) {
             if (gThreadsInMiddle != 0) {
                 IntlTest::gTest->errln(
                     "%s:%d gThreadsInMiddle = %d. Expected 0.", __FILE__, __LINE__, gThreadsInMiddle);
                 return;
             }
-            umtx_condWait(gThreadsCountChanged(), gTestMutexA());
+            gThreadsCountChanged()->wait(lock);
         }
 
         gThreadsInMiddle += 1;
-        umtx_condBroadcast(gThreadsCountChanged());
+        gThreadsCountChanged()->notify_all();
         while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) {
             if (gThreadsDone != 0) {
                 IntlTest::gTest->errln(
                     "%s:%d gThreadsDone = %d. Expected 0.", __FILE__, __LINE__, gThreadsDone);
                 return;
             }
-            umtx_condWait(gThreadsCountChanged(), gTestMutexA());
+            gThreadsCountChanged()->wait(lock);
         }
 
         gThreadsDone += 1;
-        umtx_condBroadcast(gThreadsCountChanged());
+        gThreadsCountChanged()->notify_all();
         while (gThreadsDone < TESTMUTEX_THREAD_COUNT) {
-            umtx_condWait(gThreadsCountChanged(), gTestMutexA());
+            gThreadsCountChanged()->wait(lock);
         }
-        umtx_unlock(gTestMutexA());
     }
 };
 
@@ -301,34 +300,34 @@
     gThreadsDone = 0;
     int32_t i = 0;
     TestMutexThread  threads[TESTMUTEX_THREAD_COUNT];
-    umtx_lock(gTestMutexA());
-    for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
-        if (threads[i].start() != 0) {
-            errln("%s:%d Error starting thread %d", __FILE__, __LINE__, i);
+    {
+        std::unique_lock<std::mutex> lock(gTestMutexA()->fMutex);
+        for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
+            if (threads[i].start() != 0) {
+                errln("%s:%d Error starting thread %d", __FILE__, __LINE__, i);
+                return;
+            }
+        }
+
+        // Because we are holding gTestMutexA, all of the threads should be blocked
+        // at the start of their run() function.
+        if (gThreadsStarted != 0) {
+            errln("%s:%d gThreadsStarted=%d. Expected 0.", __FILE__, __LINE__, gThreadsStarted);
             return;
         }
-    }
 
-    // Because we are holding gTestMutexA, all of the threads should be blocked
-    // at the start of their run() function.
-    if (gThreadsStarted != 0) {
-        errln("%s:%d gThreadsStarted=%d. Expected 0.", __FILE__, __LINE__, gThreadsStarted);
-        return;
-    }
-
-    while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) {
-        if (gThreadsDone != 0) {
-            errln("%s:%d gThreadsDone=%d. Expected 0.", __FILE__, __LINE__, gThreadsStarted);
-            return;
+        while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) {
+            if (gThreadsDone != 0) {
+                errln("%s:%d gThreadsDone=%d. Expected 0.", __FILE__, __LINE__, gThreadsStarted);
+                return;
+            }
+            gThreadsCountChanged()->wait(lock);
         }
-        umtx_condWait(gThreadsCountChanged(), gTestMutexA());
-    }
 
-    while (gThreadsDone < TESTMUTEX_THREAD_COUNT) {
-        umtx_condWait(gThreadsCountChanged(), gTestMutexA());
+        while (gThreadsDone < TESTMUTEX_THREAD_COUNT) {
+            gThreadsCountChanged()->wait(lock);
+        }
     }
-    umtx_unlock(gTestMutexA());
-
     for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
         threads[i].join();
     }
@@ -1173,12 +1172,12 @@
 };
 
 static UMutex *gCTMutex() {
-    static UMutex m = U_MUTEX_INITIALIZER;
-    return &m;
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
 }
-static UConditionVar *gCTConditionVar() {
-    static UConditionVar cv = U_CONDITION_INITIALIZER;
-    return &cv;
+static std::condition_variable *gCTConditionVar() {
+    static std::condition_variable *cv = STATIC_NEW(std::condition_variable);
+    return cv;
 }
 int gConditionTestOne = 1;   // Value one. Non-const, extern linkage to inhibit
                              //   compiler assuming a known value.
@@ -1189,49 +1188,48 @@
 
 // Worker thread function.
 void CondThread::run() {
-    umtx_lock(gCTMutex());
+    std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
     gStartedThreads += gConditionTestOne;
-    umtx_condBroadcast(gCTConditionVar());
+    gCTConditionVar()->notify_all();
 
     while (gStartedThreads < NUMTHREADS) {
         if (gFinishedThreads != 0) {
             IntlTest::gTest->errln("File %s, Line %d: Error, gStartedThreads = %d, gFinishedThreads = %d",
                              __FILE__, __LINE__, gStartedThreads, gFinishedThreads);
         }
-        umtx_condWait(gCTConditionVar(), gCTMutex());
+        gCTConditionVar()->wait(lock);
     }
 
     gFinishedThreads += gConditionTestOne;
     fFinished = true;
-    umtx_condBroadcast(gCTConditionVar());
+    gCTConditionVar()->notify_all();
 
     while (gFinishedThreads < NUMTHREADS) {
-        umtx_condWait(gCTConditionVar(), gCTMutex());
+        gCTConditionVar()->wait(lock);
     }
-    umtx_unlock(gCTMutex());
 }
 
 void MultithreadTest::TestConditionVariables() {
     gStartedThreads = 0;
     gFinishedThreads = 0;
     int i;
-
-    umtx_lock(gCTMutex());
     CondThread *threads[NUMTHREADS];
-    for (i=0; i<NUMTHREADS; ++i) {
-        threads[i] = new CondThread;
-        threads[i]->start();
-    }
 
-    while (gStartedThreads < NUMTHREADS) {
-        umtx_condWait(gCTConditionVar(), gCTMutex());
-    }
+    {
+        std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
+        for (i=0; i<NUMTHREADS; ++i) {
+            threads[i] = new CondThread;
+            threads[i]->start();
+        }
 
-    while (gFinishedThreads < NUMTHREADS) {
-        umtx_condWait(gCTConditionVar(), gCTMutex());
-    }
+        while (gStartedThreads < NUMTHREADS) {
+            gCTConditionVar()->wait(lock);
+        }
 
-    umtx_unlock(gCTMutex());
+        while (gFinishedThreads < NUMTHREADS) {
+            gCTConditionVar()->wait(lock);
+        }
+    }
 
     for (i=0; i<NUMTHREADS; ++i) {
         assertTrue(WHERE, threads[i]->fFinished);
@@ -1292,21 +1290,23 @@
         return result;
     }
 
-    umtx_lock(gCTMutex());
-    bool firstObject = (gObjectsCreated == 0);
-    if (firstObject) {
-        // Force the first object creation that comes through to wait
-        // until other have completed. Verifies that cache doesn't
-        // deadlock when a creation is slow.
+    bool firstObject = false;
+    {
+        std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
+        firstObject = (gObjectsCreated == 0);
+        if (firstObject) {
+            // Force the first object creation that comes through to wait
+            // until other have completed. Verifies that cache doesn't
+            // deadlock when a creation is slow.
 
-        // Note that gObjectsCreated needs to be incremeneted from 0 to 1
-        // early, to keep subsequent threads from entering this path.
-        gObjectsCreated = 1;
-        while (gObjectsCreated < 3) {
-            umtx_condWait(gCTConditionVar(), gCTMutex());
+            // Note that gObjectsCreated needs to be incremeneted from 0 to 1
+            // early, to keep subsequent threads from entering this path.
+            gObjectsCreated = 1;
+            while (gObjectsCreated < 3) {
+                gCTConditionVar()->wait(lock);
+            }
         }
     }
-    umtx_unlock(gCTMutex());
 
     const UCTMultiThreadItem *result =
         new UCTMultiThreadItem(fLoc.getLanguage());
@@ -1318,12 +1318,13 @@
  
     // Log that we created an object. The first object was already counted,
     //    don't do it again.
-    umtx_lock(gCTMutex());
-    if (!firstObject) {
-        gObjectsCreated += 1;
+    {
+        std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
+        if (!firstObject) {
+            gObjectsCreated += 1;
+        }
+        gCTConditionVar()->notify_all();
     }
-    umtx_condBroadcast(gCTConditionVar());
-    umtx_unlock(gCTMutex());
 
     return result;
 }