diff --git a/configure.ac b/configure.ac
index 8e5561243..a05896ede 100644
--- a/configure.ac
+++ b/configure.ac
@@ -659,6 +659,28 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
   ]
 )
 
+TEMP_LDFLAGS="$LDFLAGS"
+LDFLAGS="$TEMP_LDFLAGS $PTHREAD_CFLAGS"
+AC_MSG_CHECKING([for thread_local support])
+AC_LINK_IFELSE([AC_LANG_SOURCE([
+  #include <thread>
+  static thread_local int foo = 0;
+  static void run_thread() { foo++;}
+  int main(){
+  for(int i = 0; i < 10; i++) { std::thread(run_thread).detach();}
+  return foo;
+  }
+  ])],
+  [
+    AC_DEFINE(HAVE_THREAD_LOCAL,1,[Define if thread_local is supported.])
+    AC_MSG_RESULT(yes)
+  ],
+  [
+    AC_MSG_RESULT(no)
+  ]
+)
+LDFLAGS="$TEMP_LDFLAGS"
+
 # Check for different ways of gathering OS randomness
 AC_MSG_CHECKING(for Linux getrandom syscall)
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>
diff --git a/src/sync.cpp b/src/sync.cpp
index fcc6ddc35..3f51383ea 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -4,14 +4,16 @@
 
 #include <sync.h>
 
+#include <set>
 #include <util.h>
 #include <utilstrencodings.h>
 
 #include <stdio.h>
 
-#include <boost/thread.hpp>
-
 #ifdef DEBUG_LOCKCONTENTION
+#if !defined(HAVE_THREAD_LOCAL)
+static_assert(false, "thread_local is not supported");
+#endif
 void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
 {
     LogPrintf("LOCKCONTENTION: %s\n", pszName);
@@ -45,8 +47,8 @@ struct CLockLocation {
         return mutexName + "  " + sourceFile + ":" + itostr(sourceLine) + (fTry ? " (TRY)" : "");
     }
 
-    bool fTry;
 private:
+    bool fTry;
     std::string mutexName;
     std::string sourceFile;
     int sourceLine;
@@ -67,10 +69,10 @@ struct LockData {
 
     LockOrders lockorders;
     InvLockOrders invlockorders;
-    boost::mutex dd_mutex;
+    std::mutex dd_mutex;
 } static lockdata;
 
-boost::thread_specific_ptr<LockStack> lockstack;
+static thread_local std::unique_ptr<LockStack> lockstack;
 
 static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
 {
@@ -100,12 +102,12 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
 
 static void push_lock(void* c, const CLockLocation& locklocation)
 {
-    if (lockstack.get() == nullptr)
+    if (!lockstack)
         lockstack.reset(new LockStack);
 
-    boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex);
+    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
 
-    (*lockstack).push_back(std::make_pair(c, locklocation));
+    lockstack->push_back(std::make_pair(c, locklocation));
 
     for (const std::pair<void*, CLockLocation> & i : (*lockstack)) {
         if (i.first == c)
@@ -171,7 +173,7 @@ void DeleteLock(void* cs)
         // We're already shutting down.
         return;
     }
-    boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex);
+    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
     std::pair<void*, void*> item = std::make_pair(cs, nullptr);
     LockOrders::iterator it = lockdata.lockorders.lower_bound(item);
     while (it != lockdata.lockorders.end() && it->first.first == cs) {
diff --git a/src/sync.h b/src/sync.h
index b0889be76..3af27c65d 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -8,8 +8,6 @@
 
 #include <threadsafety.h>
 
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/mutex.hpp>
 #include <condition_variable>
 #include <thread>
 #include <mutex>
@@ -196,8 +194,8 @@ public:
 class CSemaphore
 {
 private:
-    boost::condition_variable condition;
-    boost::mutex mutex;
+    std::condition_variable condition;
+    std::mutex mutex;
     int value;
 
 public:
@@ -205,16 +203,14 @@ public:
 
     void wait()
     {
-        boost::unique_lock<boost::mutex> lock(mutex);
-        while (value < 1) {
-            condition.wait(lock);
-        }
+        std::unique_lock<std::mutex> lock(mutex);
+        condition.wait(lock, [&]() { return value >= 1; });
         value--;
     }
 
     bool try_wait()
     {
-        boost::unique_lock<boost::mutex> lock(mutex);
+        std::lock_guard<std::mutex> lock(mutex);
         if (value < 1)
             return false;
         value--;
@@ -224,7 +220,7 @@ public:
     void post()
     {
         {
-            boost::unique_lock<boost::mutex> lock(mutex);
+            std::lock_guard<std::mutex> lock(mutex);
             value++;
         }
         condition.notify_one();
diff --git a/src/util.h b/src/util.h
index be5c99567..08de43d29 100644
--- a/src/util.h
+++ b/src/util.h
@@ -28,6 +28,7 @@
 #include <vector>
 
 #include <boost/signals2/signal.hpp>
+#include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted
 
 // Application startup time (used for uptime calculation)
 int64_t GetStartupTime();