You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2020/02/21 18:38:16 UTC

[impala] branch master updated: IMPALA-8013: switch from boost to std locks

This is an automated email from the ASF dual-hosted git repository.

tarmstrong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git


The following commit(s) were added to refs/heads/master by this push:
     new 9d19cf6  IMPALA-8013: switch from boost to std locks
9d19cf6 is described below

commit 9d19cf6f753821188c06a0c00b36be1ee25338bf
Author: Tim Armstrong <ta...@cloudera.com>
AuthorDate: Tue Feb 11 13:25:18 2020 -0800

    IMPALA-8013: switch from boost to std locks
    
    The locks are mostly drop-in replacements that wrap
    the same pthread implementations.
    
    I went through all of the boost mutex/lock/thread-related
    includes and updated them so that the boost mutex headers
    are not pulled in. E.g. <boost/thread.hpp> is an uber-header
    that pulls in *all* of the boost mutex and thread headers.
    
    std::shared_lock doesn't exist until c++17, so we don't
    replace this.
    
    Compile Time:
    I confirmed that preprocessed files got slightly shorter,
    which translated into a slight compile time improvement
    for a full build.
    
    Before:
    real    9m27.502s
    user    64m39.775s
    sys     2m49.002s
    
    After:
    real    9m19.071s
    user    63m13.950s
    sys     2m45.066s
    
    Change-Id: I81d37490d05049919270eb6406fb3d787f78f92f
    Reviewed-on: http://gerrit.cloudera.org:8080/15208
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 be/src/benchmarks/free-lists-benchmark.cc        |  2 +-
 be/src/benchmarks/lock-benchmark.cc              |  7 +++---
 be/src/catalog/catalog-server.cc                 |  2 +-
 be/src/catalog/catalog-server.h                  |  4 ++--
 be/src/codegen/codegen-symbol-emitter.cc         |  8 +++----
 be/src/codegen/codegen-symbol-emitter.h          |  1 -
 be/src/codegen/instruction-counter-test.cc       |  1 -
 be/src/codegen/llvm-codegen.cc                   |  2 +-
 be/src/common/atomic-test.cc                     |  2 +-
 be/src/common/logging.cc                         |  7 +++---
 be/src/common/names.h                            | 21 ++++-------------
 be/src/common/object-pool.h                      |  7 +++---
 be/src/exec/blocking-join-node.h                 |  1 -
 be/src/exec/blocking-plan-root-sink.cc           |  6 ++---
 be/src/exec/blocking-plan-root-sink.h            |  2 +-
 be/src/exec/buffered-plan-root-sink.h            |  2 +-
 be/src/exec/external-data-source-executor.cc     |  1 -
 be/src/exec/hbase-table-writer.h                 |  1 -
 be/src/exec/hdfs-scan-node-base.h                |  7 +++---
 be/src/exec/hdfs-scan-node.cc                    |  3 ++-
 be/src/exec/hdfs-scan-node.h                     |  8 +++----
 be/src/exec/join-builder.h                       |  4 ++--
 be/src/exec/kudu-scan-node.h                     |  2 +-
 be/src/exec/partitioned-hash-join-node.h         |  1 -
 be/src/exec/plan-root-sink.cc                    |  6 ++---
 be/src/rpc/auth-provider.h                       |  2 +-
 be/src/rpc/impala-service-pool.cc                |  3 ++-
 be/src/rpc/impala-service-pool.h                 |  4 ++--
 be/src/rpc/rpc-trace.h                           |  3 +--
 be/src/rpc/thrift-server.cc                      |  4 ++--
 be/src/rpc/thrift-server.h                       |  7 +++---
 be/src/rpc/thrift-util.cc                        |  1 -
 be/src/runtime/bufferpool/buffer-allocator.cc    |  3 +--
 be/src/runtime/bufferpool/buffer-allocator.h     |  4 ++--
 be/src/runtime/bufferpool/buffer-pool-internal.h | 15 ++++++------
 be/src/runtime/bufferpool/buffer-pool.cc         |  2 +-
 be/src/runtime/bufferpool/buffer-pool.h          |  1 -
 be/src/runtime/bufferpool/free-list.h            |  2 --
 be/src/runtime/bufferpool/reservation-tracker.cc |  1 +
 be/src/runtime/bufferpool/reservation-tracker.h  |  1 -
 be/src/runtime/client-cache.h                    |  8 +++----
 be/src/runtime/coordinator-backend-state.cc      |  2 +-
 be/src/runtime/coordinator-backend-state.h       | 10 ++++----
 be/src/runtime/coordinator-filter-state.h        |  1 +
 be/src/runtime/coordinator.h                     |  1 -
 be/src/runtime/dml-exec-state.cc                 |  4 ++--
 be/src/runtime/dml-exec-state.h                  |  4 ++--
 be/src/runtime/fragment-instance-state.cc        |  7 +++---
 be/src/runtime/fragment-instance-state.h         |  2 +-
 be/src/runtime/hbase-table-factory.cc            |  2 +-
 be/src/runtime/hbase-table-factory.h             |  6 +++--
 be/src/runtime/hbase-table.h                     |  1 -
 be/src/runtime/hdfs-fs-cache.cc                  |  3 ++-
 be/src/runtime/hdfs-fs-cache.h                   |  4 ++--
 be/src/runtime/initial-reservations.cc           |  2 +-
 be/src/runtime/io/disk-io-mgr-internal.h         |  6 ++---
 be/src/runtime/io/disk-io-mgr-stress.cc          |  4 ++--
 be/src/runtime/io/disk-io-mgr-stress.h           |  1 -
 be/src/runtime/io/disk-io-mgr.h                  |  3 +--
 be/src/runtime/io/handle-cache.h                 |  3 +--
 be/src/runtime/io/handle-cache.inline.h          |  8 +++----
 be/src/runtime/io/request-context.cc             |  5 ++--
 be/src/runtime/io/request-context.h              | 16 ++++++-------
 be/src/runtime/io/request-ranges.h               | 14 ++++++------
 be/src/runtime/io/scan-range.cc                  |  3 +--
 be/src/runtime/krpc-data-stream-mgr.cc           |  5 ++--
 be/src/runtime/krpc-data-stream-mgr.h            |  5 ++--
 be/src/runtime/krpc-data-stream-recvr.cc         |  4 +---
 be/src/runtime/krpc-data-stream-recvr.h          |  2 +-
 be/src/runtime/lib-cache.cc                      |  5 ++--
 be/src/runtime/lib-cache.h                       | 11 ++++-----
 be/src/runtime/mem-tracker.h                     |  6 ++---
 be/src/runtime/query-state.cc                    |  9 ++++----
 be/src/runtime/runtime-filter-bank.cc            |  1 -
 be/src/runtime/runtime-filter-bank.h             |  8 +++----
 be/src/runtime/runtime-filter.h                  |  4 ++--
 be/src/runtime/runtime-filter.inline.h           |  2 --
 be/src/runtime/runtime-state.cc                  |  4 ++--
 be/src/runtime/runtime-state.h                   | 10 ++++----
 be/src/runtime/scanner-mem-limiter.cc            |  2 +-
 be/src/runtime/sorted-run-merger.h               |  2 +-
 be/src/runtime/sorter.cc                         |  1 +
 be/src/runtime/thread-resource-mgr.cc            |  2 +-
 be/src/runtime/thread-resource-mgr.h             |  6 ++---
 be/src/runtime/tmp-file-mgr-test.cc              |  2 +-
 be/src/runtime/tmp-file-mgr.cc                   |  2 +-
 be/src/runtime/tmp-file-mgr.h                    |  4 ++--
 be/src/scheduling/admission-controller.cc        |  1 +
 be/src/scheduling/admission-controller.h         |  4 ++--
 be/src/scheduling/cluster-membership-mgr.h       |  6 ++---
 be/src/scheduling/scheduler.h                    |  2 +-
 be/src/service/child-query.h                     |  8 +++----
 be/src/service/client-request-state.h            | 20 ++++++++--------
 be/src/service/impala-hs2-server.cc              |  4 ++--
 be/src/service/impala-http-handler.cc            |  2 +-
 be/src/service/impala-server.h                   | 24 ++++++++++----------
 be/src/statestore/failure-detector.cc            |  3 ++-
 be/src/statestore/failure-detector.h             |  6 ++---
 be/src/statestore/statestore-subscriber.cc       |  6 ++---
 be/src/statestore/statestore-subscriber.h        |  8 +++----
 be/src/statestore/statestore.cc                  |  1 -
 be/src/statestore/statestore.h                   |  4 ++--
 be/src/testutil/impalad-query-executor.h         |  1 -
 be/src/transport/TSaslServerTransport.cpp        |  5 ++--
 be/src/transport/TSaslServerTransport.h          |  7 +++---
 be/src/util/blocking-queue-test.cc               |  5 ++--
 be/src/util/blocking-queue.h                     | 26 ++++++++++-----------
 be/src/util/collection-metrics.h                 | 15 ++++++------
 be/src/util/condition-variable.h                 |  9 ++++----
 be/src/util/cyclic-barrier-test.cc               |  2 +-
 be/src/util/cyclic-barrier.cc                    |  3 +--
 be/src/util/cyclic-barrier.h                     |  8 +++----
 be/src/util/hdfs-bulk-ops.h                      |  4 ++--
 be/src/util/histogram-metric.h                   |  2 +-
 be/src/util/internal-queue-test.cc               |  5 ++--
 be/src/util/internal-queue.h                     | 29 ++++++++++++------------
 be/src/util/memory-metrics.cc                    |  8 +++----
 be/src/util/memory-metrics.h                     |  4 ++--
 be/src/util/metrics.h                            | 10 ++++----
 be/src/util/periodic-counter-updater.h           |  2 +-
 be/src/util/promise-test.cc                      |  2 +-
 be/src/util/promise.h                            | 12 +++++-----
 be/src/util/runtime-profile-counters.h           |  6 ++---
 be/src/util/runtime-profile.cc                   |  7 +++---
 be/src/util/runtime-profile.h                    |  4 ++--
 be/src/util/sharded-query-map-util.h             |  4 ++--
 be/src/util/simple-logger.cc                     |  3 ++-
 be/src/util/simple-logger.h                      |  4 ++--
 be/src/util/stopwatch.h                          | 10 ++++----
 be/src/util/thread-pool-test.cc                  |  5 ++--
 be/src/util/thread-pool.h                        | 14 ++++++------
 be/src/util/thread.h                             |  2 +-
 be/src/util/webserver.cc                         |  2 +-
 133 files changed, 330 insertions(+), 367 deletions(-)

diff --git a/be/src/benchmarks/free-lists-benchmark.cc b/be/src/benchmarks/free-lists-benchmark.cc
index cbadc03..396c51f 100644
--- a/be/src/benchmarks/free-lists-benchmark.cc
+++ b/be/src/benchmarks/free-lists-benchmark.cc
@@ -23,7 +23,7 @@
 #include <utility>
 #include <vector>
 
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
 
 #include "common/object-pool.h"
 #include "gutil/strings/substitute.h"
diff --git a/be/src/benchmarks/lock-benchmark.cc b/be/src/benchmarks/lock-benchmark.cc
index b29d1c7..3ce9717 100644
--- a/be/src/benchmarks/lock-benchmark.cc
+++ b/be/src/benchmarks/lock-benchmark.cc
@@ -19,9 +19,10 @@
 #include <stdlib.h>
 #include <iostream>
 #include <sstream>
+#include <mutex>
+#include <sstream>
 #include <vector>
-#include <boost/thread.hpp>
-#include <boost/thread/pthread/mutex.hpp>
+#include <boost/thread/thread.hpp>
 #include "util/benchmark.h"
 #include "util/cpu-info.h"
 #include "util/spinlock.h"
@@ -80,7 +81,7 @@ struct TestData {
 mutex lock_;
 SpinLock spinlock_;
 
-typedef function<void (int64_t, int64_t*)> Fn;
+typedef std::function<void (int64_t, int64_t*)> Fn;
 
 void UnlockedConsumeThread(int64_t n, int64_t* value) {
   // volatile to prevent compile from collapsing this loop to *value -= n
diff --git a/be/src/catalog/catalog-server.cc b/be/src/catalog/catalog-server.cc
index f38aa5c..57966f7 100644
--- a/be/src/catalog/catalog-server.cc
+++ b/be/src/catalog/catalog-server.cc
@@ -306,7 +306,7 @@ void CatalogServer::UpdateCatalogTopicCallback(
       incoming_topic_deltas.find(CatalogServer::IMPALA_CATALOG_TOPIC);
   if (topic == incoming_topic_deltas.end()) return;
 
-  try_mutex::scoped_try_lock l(catalog_lock_);
+  unique_lock<mutex> l(catalog_lock_, std::try_to_lock);
   // Return if unable to acquire the catalog_lock_ or if the topic update data is
   // not yet ready for processing. This indicates the catalog_update_gathering_thread_
   // is still building a topic update.
diff --git a/be/src/catalog/catalog-server.h b/be/src/catalog/catalog-server.h
index 65168d1..a3f1b3f 100644
--- a/be/src/catalog/catalog-server.h
+++ b/be/src/catalog/catalog-server.h
@@ -17,10 +17,10 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
 #include <vector>
 #include <boost/shared_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_set.hpp>
 
 #include "gen-cpp/CatalogService.h"
@@ -100,7 +100,7 @@ class CatalogServer {
 
   /// Protects catalog_update_cv_, pending_topic_updates_,
   /// catalog_objects_to/from_version_, and last_sent_catalog_version.
-  boost::mutex catalog_lock_;
+  std::mutex catalog_lock_;
 
   /// Condition variable used to signal when the catalog_update_gathering_thread_ should
   /// fetch its next set of updates from the JniCatalog. At the end of each statestore
diff --git a/be/src/codegen/codegen-symbol-emitter.cc b/be/src/codegen/codegen-symbol-emitter.cc
index 0706d69..992493b 100644
--- a/be/src/codegen/codegen-symbol-emitter.cc
+++ b/be/src/codegen/codegen-symbol-emitter.cc
@@ -17,12 +17,14 @@
 
 #include "codegen/codegen-symbol-emitter.h"
 
-#include <boost/scoped_ptr.hpp>
-#include <boost/thread/locks.hpp>
+#include <unistd.h>
 #include <cstdio>
 #include <fstream>
 #include <iostream>
 #include <memory>
+#include <mutex>
+#include <boost/scoped_ptr.hpp>
+#include <llvm-c/Disassembler.h>
 #include <llvm/CodeGen/MachineFunction.h>
 #include <llvm/DebugInfo/DIContext.h>
 #include <llvm/DebugInfo/DWARF/DWARFContext.h>
@@ -31,8 +33,6 @@
 #include <llvm/Object/SymbolSize.h>
 #include <llvm/Support/Debug.h>
 #include "llvm/Support/raw_ostream.h"
-#include <llvm-c/Disassembler.h>
-#include <unistd.h>
 
 #include "common/logging.h"
 #include "gutil/strings/substitute.h"
diff --git a/be/src/codegen/codegen-symbol-emitter.h b/be/src/codegen/codegen-symbol-emitter.h
index 04967fd..bad30f5 100644
--- a/be/src/codegen/codegen-symbol-emitter.h
+++ b/be/src/codegen/codegen-symbol-emitter.h
@@ -19,7 +19,6 @@
 #ifndef IMPALA_CODEGEN_JIT_SYMBOL_EMITTER_H
 #define IMPALA_CODEGEN_JIT_SYMBOL_EMITTER_H
 
-#include <boost/thread/locks.hpp>
 #include <boost/unordered_map.hpp>
 #include <iosfwd>
 #include <llvm/ExecutionEngine/JITEventListener.h>
diff --git a/be/src/codegen/instruction-counter-test.cc b/be/src/codegen/instruction-counter-test.cc
index d801c2d..880127a 100644
--- a/be/src/codegen/instruction-counter-test.cc
+++ b/be/src/codegen/instruction-counter-test.cc
@@ -15,7 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#include <boost/thread/thread.hpp>
 #include <string>
 
 #include "llvm/IR/Module.h"
diff --git a/be/src/codegen/llvm-codegen.cc b/be/src/codegen/llvm-codegen.cc
index 705fa48..4975192 100644
--- a/be/src/codegen/llvm-codegen.cc
+++ b/be/src/codegen/llvm-codegen.cc
@@ -22,8 +22,8 @@
 #include <sstream>
 #include <unordered_set>
 
+#include <mutex>
 #include <boost/algorithm/string.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <gutil/strings/substitute.h>
 
 #include <llvm/ADT/Triple.h>
diff --git a/be/src/common/atomic-test.cc b/be/src/common/atomic-test.cc
index 3ce476b..b634123 100644
--- a/be/src/common/atomic-test.cc
+++ b/be/src/common/atomic-test.cc
@@ -16,7 +16,7 @@
 // under the License.
 
 #include <string>
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
 
 #include "common/atomic.h"
 #include "testutil/gtest-util.h"
diff --git a/be/src/common/logging.cc b/be/src/common/logging.cc
index 46407ae..f4a1de8 100644
--- a/be/src/common/logging.cc
+++ b/be/src/common/logging.cc
@@ -23,9 +23,8 @@
 #include <fstream>
 #include <iostream>
 #include <map>
+#include <mutex>
 #include <sstream>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_generators.hpp>
 #include <boost/uuid/uuid_io.hpp>
@@ -83,7 +82,7 @@ void MessageListener(string* s, bool* changed) {
 mutex logging_mutex;
 
 void impala::InitGoogleLoggingSafe(const char* arg) {
-  mutex::scoped_lock logging_lock(logging_mutex);
+  lock_guard<mutex> logging_lock(logging_mutex);
   if (logging_initialized) return;
   if (!FLAGS_log_filename.empty()) {
     for (int severity = google::INFO; severity <= google::FATAL; ++severity) {
@@ -174,7 +173,7 @@ void impala::ShutdownLogging() {
   // This method may only correctly be called once (which this lock does not
   // enforce), but this lock protects against concurrent calls with
   // InitGoogleLoggingSafe
-  mutex::scoped_lock logging_lock(logging_mutex);
+  lock_guard<mutex> logging_lock(logging_mutex);
   google::ShutdownGoogleLogging();
 }
 
diff --git a/be/src/common/names.h b/be/src/common/names.h
index 9e47726..5173006 100644
--- a/be/src/common/names.h
+++ b/be/src/common/names.h
@@ -136,10 +136,11 @@ using boost::thread;
 using boost::thread_group;
 #endif
 
-#ifdef BOOST_THREAD_PTHREAD_MUTEX_HPP
-using boost::mutex;
-using boost::timed_mutex;
-using boost::try_mutex;
+#ifdef _GLIBCXX_MUTEX
+using std::lock_guard;
+using std::mutex;
+using std::timed_mutex;
+using std::unique_lock;
 #endif
 
 #ifdef BOOST_LEXICAL_CAST_INCLUDED
@@ -150,19 +151,7 @@ using boost::lexical_cast;
 using boost::shared_mutex;
 #endif
 
-
-/// In older versions of boost, when including mutex.hpp, it would include locks.hpp that
-/// would in turn provide lock_guard<>. In more recent versions, including mutex.hpp would
-/// include lock_types.hpp that does not provide lock_guard<>. This check verifies if boost
-/// locks have been included and makes sure to only include lock_guard if the provided lock
-/// implementations were not included using lock_types.hpp (for older boost versions) or if
-/// lock_guard.hpp was explicitly included.
-#if (defined(BOOST_THREAD_LOCKS_HPP) && BOOST_VERSION < 105300)  || defined(BOOST_THREAD_LOCK_GUARD_HPP)
-using boost::lock_guard;
-#endif
-
 #if defined(BOOST_THREAD_LOCKS_HPP) || defined(BOOST_THREAD_LOCK_TYPES_HPP)
-using boost::unique_lock;
 using boost::shared_lock;
 using boost::upgrade_lock;
 #endif
diff --git a/be/src/common/object-pool.h b/be/src/common/object-pool.h
index fa6d725..914cfd7 100644
--- a/be/src/common/object-pool.h
+++ b/be/src/common/object-pool.h
@@ -17,9 +17,8 @@
 
 #pragma once
 
+#include <mutex>
 #include <vector>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "gutil/macros.h"
 #include "util/spinlock.h"
@@ -37,14 +36,14 @@ class ObjectPool {
   template <class T>
   T* Add(T* t) {
     // TODO: Consider using a lock-free structure.
-    boost::lock_guard<SpinLock> l(lock_);
+    std::lock_guard<SpinLock> l(lock_);
     objects_.emplace_back(
         Element{t, [](void* obj) { delete reinterpret_cast<T*>(obj); }});
     return t;
   }
 
   void Clear() {
-    boost::lock_guard<SpinLock> l(lock_);
+    std::lock_guard<SpinLock> l(lock_);
     for (Element& elem : objects_) elem.delete_fn(elem.obj);
     objects_.clear();
   }
diff --git a/be/src/exec/blocking-join-node.h b/be/src/exec/blocking-join-node.h
index f801ad1..413c913 100644
--- a/be/src/exec/blocking-join-node.h
+++ b/be/src/exec/blocking-join-node.h
@@ -20,7 +20,6 @@
 #define IMPALA_EXEC_BLOCKING_JOIN_NODE_H
 
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread.hpp>
 #include <string>
 
 #include "exec/exec-node.h"
diff --git a/be/src/exec/blocking-plan-root-sink.cc b/be/src/exec/blocking-plan-root-sink.cc
index 8e04997..5db0ebe 100644
--- a/be/src/exec/blocking-plan-root-sink.cc
+++ b/be/src/exec/blocking-plan-root-sink.cc
@@ -24,11 +24,11 @@
 #include "util/pretty-printer.h"
 
 #include <memory>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 using namespace std;
-using boost::unique_lock;
-using boost::mutex;
+using std::mutex;
+using std::unique_lock;
 
 namespace impala {
 
diff --git a/be/src/exec/blocking-plan-root-sink.h b/be/src/exec/blocking-plan-root-sink.h
index 0a5b849..5fe1b8a 100644
--- a/be/src/exec/blocking-plan-root-sink.h
+++ b/be/src/exec/blocking-plan-root-sink.h
@@ -77,7 +77,7 @@ class BlockingPlanRootSink : public PlanRootSink {
 
  private:
   /// Protects all members, including the condition variables.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Waited on by the sender only. Signalled when the consumer has written results_ and
   /// num_rows_requested_, and so the sender may begin satisfying that request for rows
diff --git a/be/src/exec/buffered-plan-root-sink.h b/be/src/exec/buffered-plan-root-sink.h
index 7be257e..586423d 100644
--- a/be/src/exec/buffered-plan-root-sink.h
+++ b/be/src/exec/buffered-plan-root-sink.h
@@ -85,7 +85,7 @@ class BufferedPlanRootSink : public PlanRootSink {
   static const int MAX_FETCH_SIZE = QueryState::DEFAULT_BATCH_SIZE * 100;
 
   /// Protects the RowBatchQueue and all ConditionVariables.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Waited on by the consumer inside GetNext() until rows are available for consumption.
   /// Signaled when the producer adds a RowBatch to the queue. Also signaled by
diff --git a/be/src/exec/external-data-source-executor.cc b/be/src/exec/external-data-source-executor.cc
index 0b58e3f..34ae9e6 100644
--- a/be/src/exec/external-data-source-executor.cc
+++ b/be/src/exec/external-data-source-executor.cc
@@ -17,7 +17,6 @@
 
 #include "exec/external-data-source-executor.h"
 
-#include <boost/thread.hpp>
 #include <list>
 #include <string>
 
diff --git a/be/src/exec/hbase-table-writer.h b/be/src/exec/hbase-table-writer.h
index 43ddaee..39f6e84 100644
--- a/be/src/exec/hbase-table-writer.h
+++ b/be/src/exec/hbase-table-writer.h
@@ -19,7 +19,6 @@
 #define IMPALA_EXEC_HBASE_TABLE_WRITER_H
 
 #include <jni.h>
-#include <boost/thread.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <vector>
 #include <string>
diff --git a/be/src/exec/hdfs-scan-node-base.h b/be/src/exec/hdfs-scan-node-base.h
index 760172b..6b5a7a5 100644
--- a/be/src/exec/hdfs-scan-node-base.h
+++ b/be/src/exec/hdfs-scan-node-base.h
@@ -21,12 +21,13 @@
 
 #include <stdint.h>
 #include <memory>
+#include <tuple>
 #include <unordered_set>
 #include <vector>
-#include <tuple>
 
-#include <boost/unordered_map.hpp>
 #include <boost/scoped_ptr.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/unordered_map.hpp>
 
 #include "exec/filter-context.h"
 #include "exec/scan-node.h"
@@ -474,7 +475,7 @@ class HdfsScanNodeBase : public ScanNode {
   /// Scanner specific per file metadata (e.g. header information) and associated lock.
   /// Key of the map is partition_id, filename pair
   /// TODO: Remove this lock when removing the legacy scanners and scan nodes.
-  boost::mutex metadata_lock_;
+  std::mutex metadata_lock_;
   std::unordered_map<PartitionFileKey, void*, pair_hash> per_file_metadata_;
 
   /// Conjuncts for each materialized tuple (top-level row batch tuples and collection
diff --git a/be/src/exec/hdfs-scan-node.cc b/be/src/exec/hdfs-scan-node.cc
index cb0eb01..1af0ef4 100644
--- a/be/src/exec/hdfs-scan-node.cc
+++ b/be/src/exec/hdfs-scan-node.cc
@@ -17,6 +17,7 @@
 
 #include "exec/hdfs-scan-node.h"
 
+#include <chrono>
 #include <memory>
 #include <sstream>
 
@@ -288,7 +289,7 @@ void HdfsScanNode::ThreadTokenAvailableCb(ThreadResourcePool* pool) {
     // TODO: This still leans heavily on starvation-free locks, come up with a more
     // correct way to communicate between this method and ScannerThread().
     if (done()) break;
-    unique_lock<timed_mutex> lock(lock_, boost::chrono::milliseconds(10));
+    unique_lock<timed_mutex> lock(lock_, std::chrono::milliseconds(10));
     if (!lock.owns_lock()) {
       continue;
     }
diff --git a/be/src/exec/hdfs-scan-node.h b/be/src/exec/hdfs-scan-node.h
index 1ee7e8d..8d331e3 100644
--- a/be/src/exec/hdfs-scan-node.h
+++ b/be/src/exec/hdfs-scan-node.h
@@ -17,13 +17,13 @@
 
 #pragma once
 
+#include <stdint.h>
 #include <map>
 #include <memory>
-#include <stdint.h>
+#include <mutex>
 #include <vector>
 
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/atomic.h"
 #include "exec/filter-context.h"
@@ -122,7 +122,7 @@ class HdfsScanNode : public HdfsScanNodeBase {
   /// together, this lock must be taken first. This is a "timed_mutex" to allow specifying
   /// a timeout when acquiring the mutex. Almost all code locations acquire the mutex
   /// without a timeout; see ThreadTokenAvailableCb for a location using a timeout.
-  boost::timed_mutex lock_;
+  std::timed_mutex lock_;
 
   /// Protects file_type_counts_. Cannot be taken together with any other lock
   /// except lock_, and if so, lock_ must be taken first.
@@ -186,7 +186,7 @@ class HdfsScanNode : public HdfsScanNodeBase {
   /// needed. Always holds onto at least the minimum reservation to avoid violating the
   /// invariants of ExecNode::buffer_pool_client_. 'lock_' must be held via 'lock'.
   void ReturnReservationFromScannerThread(
-      const boost::unique_lock<boost::timed_mutex>& lock, int64_t bytes);
+      const std::unique_lock<std::timed_mutex>& lock, int64_t bytes);
 
   /// Checks for eos conditions and returns batches from the row batch queue.
   Status GetNextInternal(RuntimeState* state, RowBatch* row_batch, bool* eos)
diff --git a/be/src/exec/join-builder.h b/be/src/exec/join-builder.h
index 3e8b148..b9e742e 100644
--- a/be/src/exec/join-builder.h
+++ b/be/src/exec/join-builder.h
@@ -17,7 +17,7 @@
 
 #pragma once
 
-#include <boost/thread/locks.hpp>
+#include <mutex>
 
 #include "exec/data-sink.h"
 #include "util/condition-variable.h"
@@ -156,7 +156,7 @@ class JoinBuilder : public DataSink {
 
   // Lock used for synchronization between threads from the build and probe side (i.e.
   // the build fragment thread and the probe-side thread executing the join node).
-  boost::mutex separate_build_lock_;
+  std::mutex separate_build_lock_;
 
   // Probe-side threads block on this while waiting for initial_build_complete_ = true
   // (or for probe finstance cancellation).
diff --git a/be/src/exec/kudu-scan-node.h b/be/src/exec/kudu-scan-node.h
index 6d41f33..0d53149 100644
--- a/be/src/exec/kudu-scan-node.h
+++ b/be/src/exec/kudu-scan-node.h
@@ -56,7 +56,7 @@ class KuduScanNode : public KuduScanNodeBase {
   /// Protects access to state accessed by scanner threads, such as 'status_' and 'done_'.
   /// Writers to 'done_' must hold lock to prevent races when updating, but readers can
   /// read without holding lock, provided they can tolerate stale reads.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// The current status of the scan, set to non-OK if any problems occur, e.g. if an
   /// error occurs in a scanner.
diff --git a/be/src/exec/partitioned-hash-join-node.h b/be/src/exec/partitioned-hash-join-node.h
index 78cc851..99a575d 100644
--- a/be/src/exec/partitioned-hash-join-node.h
+++ b/be/src/exec/partitioned-hash-join-node.h
@@ -22,7 +22,6 @@
 #include <memory>
 #include <string>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread.hpp>
 
 #include "exec/blocking-join-node.h"
 #include "exec/exec-node.h"
diff --git a/be/src/exec/plan-root-sink.cc b/be/src/exec/plan-root-sink.cc
index fc506ef..6013842 100644
--- a/be/src/exec/plan-root-sink.cc
+++ b/be/src/exec/plan-root-sink.cc
@@ -27,11 +27,11 @@
 #include "util/pretty-printer.h"
 
 #include <memory>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 using namespace std;
-using boost::unique_lock;
-using boost::mutex;
+using std::mutex;
+using std::unique_lock;
 
 namespace impala {
 
diff --git a/be/src/rpc/auth-provider.h b/be/src/rpc/auth-provider.h
index b3026fc..9179505 100644
--- a/be/src/rpc/auth-provider.h
+++ b/be/src/rpc/auth-provider.h
@@ -17,8 +17,8 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
-#include <boost/thread/pthread/mutex.hpp>
 #include <sasl/sasl.h>
 
 #include "common/status.h"
diff --git a/be/src/rpc/impala-service-pool.cc b/be/src/rpc/impala-service-pool.cc
index 304dfe9..5a8b275 100644
--- a/be/src/rpc/impala-service-pool.cc
+++ b/be/src/rpc/impala-service-pool.cc
@@ -18,9 +18,9 @@
 #include "rpc/impala-service-pool.h"
 
 #include <memory>
+#include <mutex>
 #include <string>
 #include <vector>
-#include <boost/thread/pthread/mutex.hpp>
 #include <glog/logging.h>
 
 #include "exec/kudu-util.h"
@@ -39,6 +39,7 @@
 #include "runtime/exec-env.h"
 #include "runtime/mem-tracker.h"
 #include "util/pretty-printer.h"
+#include "util/thread.h"
 
 #include "common/names.h"
 #include "common/status.h"
diff --git a/be/src/rpc/impala-service-pool.h b/be/src/rpc/impala-service-pool.h
index 01b4301..9721757 100644
--- a/be/src/rpc/impala-service-pool.h
+++ b/be/src/rpc/impala-service-pool.h
@@ -29,10 +29,10 @@
 #include "kudu/util/status.h"
 #include "util/histogram-metric.h"
 #include "util/spinlock.h"
-#include "util/thread.h"
 
 namespace impala {
 class MemTracker;
+class Thread;
 
 /// A pool of threads that handle new incoming RPC calls.
 /// Also includes a queue that calls get pushed onto for handling by the pool.
@@ -110,7 +110,7 @@ class ImpalaServicePool : public kudu::rpc::RpcService {
   /// Protects against concurrent Shutdown() operations.
   /// TODO: This seems implausible given our current usage pattern.
   /// Consider removing lock.
-  boost::mutex shutdown_lock_;
+  std::mutex shutdown_lock_;
   bool closing_ = false;
 
   /// The address this service is running on.
diff --git a/be/src/rpc/rpc-trace.h b/be/src/rpc/rpc-trace.h
index 0a743c8..c54de76 100644
--- a/be/src/rpc/rpc-trace.h
+++ b/be/src/rpc/rpc-trace.h
@@ -22,7 +22,6 @@
 #include "util/internal-queue.h"
 
 #include <thrift/TProcessor.h>
-#include <boost/thread/thread.hpp>
 #include <boost/unordered_map.hpp>
 
 #include <rapidjson/document.h>
@@ -112,7 +111,7 @@ class RpcEventHandler : public apache::thrift::TProcessorEventHandler {
   };
 
   /// Protects method_map_ and rpc_counter_
-  boost::mutex method_map_lock_;
+  std::mutex method_map_lock_;
 
   /// Map of all methods, populated lazily as they are invoked for the first time.
   MethodMap method_map_;
diff --git a/be/src/rpc/thrift-server.cc b/be/src/rpc/thrift-server.cc
index 5dab197..abc3fcf 100644
--- a/be/src/rpc/thrift-server.cc
+++ b/be/src/rpc/thrift-server.cc
@@ -15,10 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#include <mutex>
 #include <boost/algorithm/string.hpp>
 #include <boost/filesystem.hpp>
-#include <boost/thread.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/uuid/uuid_io.hpp>
 
 #include <openssl/err.h>
@@ -46,6 +45,7 @@
 #include "util/network-util.h"
 #include "util/openssl-util.h"
 #include "util/os-util.h"
+#include "util/thread.h"
 #include "util/uid-util.h"
 
 #include "common/names.h"
diff --git a/be/src/rpc/thrift-server.h b/be/src/rpc/thrift-server.h
index adf1b63..9a122b6 100644
--- a/be/src/rpc/thrift-server.h
+++ b/be/src/rpc/thrift-server.h
@@ -17,9 +17,9 @@
 
 #pragma once
 
+#include <mutex>
 #include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 #include <boost/uuid/uuid_generators.hpp>
 #include <thrift/TProcessor.h>
@@ -28,6 +28,7 @@
 #include <thrift/transport/TSSLSocket.h>
 
 #include "common/status.h"
+#include "util/condition-variable.h"
 #include "util/metrics-fwd.h"
 #include "util/thread.h"
 
@@ -215,7 +216,7 @@ class ThriftServer {
     /// Lock used to ensure that there are no missed notifications between starting the
     /// supervision thread and calling signal_cond_.WaitUntil. Also used to ensure
     /// thread-safe access to members of thrift_server_
-    boost::mutex signal_lock_;
+    std::mutex signal_lock_;
 
     /// Condition variable that is notified by the supervision thread once either
     /// a) all is well or b) an error occurred.
@@ -331,7 +332,7 @@ class ThriftServer {
   ConnectionHandlerIf* connection_handler_;
 
   /// Protects connection_contexts_
-  boost::mutex connection_contexts_lock_;
+  std::mutex connection_contexts_lock_;
 
   /// Map of active connection context to a shared_ptr containing that context; when an
   /// item is removed from the map, it is automatically freed.
diff --git a/be/src/rpc/thrift-util.cc b/be/src/rpc/thrift-util.cc
index 34384a0..dc7b972 100644
--- a/be/src/rpc/thrift-util.cc
+++ b/be/src/rpc/thrift-util.cc
@@ -17,7 +17,6 @@
 
 #include "rpc/thrift-util.h"
 
-#include <boost/thread.hpp>
 #include <thrift/config.h>
 
 #include "util/hash-util.h"
diff --git a/be/src/runtime/bufferpool/buffer-allocator.cc b/be/src/runtime/bufferpool/buffer-allocator.cc
index 7f6db92..6bca177 100644
--- a/be/src/runtime/bufferpool/buffer-allocator.cc
+++ b/be/src/runtime/bufferpool/buffer-allocator.cc
@@ -79,8 +79,7 @@ class BufferPool::FreeBufferArena : public CacheLineAligned {
   /// number of bytes freed and the actual number of bytes claimed.
   ///
   /// Caller should not hold 'lock_'. If 'arena_lock' is non-null, ownership of the
-  /// arena lock is transferred to the caller. Uses std::unique_lock instead of
-  /// boost::unique_lock because it is movable.
+  /// arena lock is transferred to the caller.
   pair<int64_t, int64_t> FreeSystemMemory(int64_t target_bytes_to_free,
       int64_t target_bytes_to_claim, std::unique_lock<SpinLock>* arena_lock);
 
diff --git a/be/src/runtime/bufferpool/buffer-allocator.h b/be/src/runtime/bufferpool/buffer-allocator.h
index 1c0b264..244a039 100644
--- a/be/src/runtime/bufferpool/buffer-allocator.h
+++ b/be/src/runtime/bufferpool/buffer-allocator.h
@@ -102,7 +102,7 @@ class BufferPool::BufferAllocator {
   /// client's lock via 'client_lock' so that moving the page between the client list and
   /// the free page list is atomic. Caller must not hold 'FreeBufferArena::lock_' or any
   /// Page::lock.
-  void AddCleanPage(const boost::unique_lock<boost::mutex>& client_lock, Page* page);
+  void AddCleanPage(const std::unique_lock<std::mutex>& client_lock, Page* page);
 
   /// Removes a clean page 'page' from a clean page list and returns true, if present in
   /// one of the lists. Returns true if it was present. If 'claim_buffer' is true, the
@@ -112,7 +112,7 @@ class BufferPool::BufferAllocator {
   /// client list and the free page list is atomic. Caller must not hold
   /// 'FreeBufferArena::lock_' or any Page::lock.
   bool RemoveCleanPage(
-      const boost::unique_lock<boost::mutex>& client_lock, bool claim_buffer, Page* page);
+      const std::unique_lock<std::mutex>& client_lock, bool claim_buffer, Page* page);
 
   /// Periodically called to release free buffers back to the SystemAllocator. Releases
   /// buffers based on recent allocation patterns, trying to minimise the number of
diff --git a/be/src/runtime/bufferpool/buffer-pool-internal.h b/be/src/runtime/bufferpool/buffer-pool-internal.h
index 98d9264..36fa631 100644
--- a/be/src/runtime/bufferpool/buffer-pool-internal.h
+++ b/be/src/runtime/bufferpool/buffer-pool-internal.h
@@ -76,8 +76,7 @@
 
 #include <iosfwd>
 #include <memory>
-
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 #include "runtime/bufferpool/buffer-pool-counters.h"
 #include "runtime/bufferpool/buffer-pool.h"
@@ -261,7 +260,7 @@ class BufferPool::Client {
   /// internal accounting and release the buffer to the client's reservation. No page or
   /// client locks should be held by the caller.
   void FreedBuffer(int64_t len) {
-    boost::lock_guard<boost::mutex> cl(lock_);
+    std::lock_guard<std::mutex> cl(lock_);
     reservation_.ReleaseTo(len);
     buffers_allocated_bytes_ -= len;
     DCHECK_CONSISTENCY();
@@ -270,14 +269,14 @@ class BufferPool::Client {
   /// Wait for the in-flight write for 'page' to complete.
   /// 'lock_' must be held by the caller via 'client_lock'. page->buffer_lock should
   /// not be held.
-  void WaitForWrite(boost::unique_lock<boost::mutex>* client_lock, Page* page);
+  void WaitForWrite(std::unique_lock<std::mutex>* client_lock, Page* page);
 
   /// Test helper: wait for all in-flight writes to complete.
   /// 'lock_' must not be held by the caller.
   void WaitForAllWrites();
 
   /// Asserts that 'client_lock' is holding 'lock_'.
-  void DCheckHoldsLock(const boost::unique_lock<boost::mutex>& client_lock) {
+  void DCheckHoldsLock(const std::unique_lock<std::mutex>& client_lock) {
     DCHECK(client_lock.mutex() == &lock_ && client_lock.owns_lock());
   }
 
@@ -315,7 +314,7 @@ class BufferPool::Client {
   /// invariants after the allocation. 'lock_' should be held by the caller via
   /// 'client_lock'. If 'lazy_flush' is true, only write out pages if needed to reclaim
   /// 'len', and do not return a write error if the error prevents flushing enough pages.
-  Status CleanPages(boost::unique_lock<boost::mutex>* client_lock, int64_t len,
+  Status CleanPages(std::unique_lock<std::mutex>* client_lock, int64_t len,
       bool lazy_flush = false);
 
   /// Initiates asynchronous writes of dirty unpinned pages to disk. Ensures that at
@@ -333,7 +332,7 @@ class BufferPool::Client {
   /// locked by the caller via 'client_lock' and handle->page must be unlocked.
   /// 'client_lock' is released then reacquired.
   Status StartMoveEvictedToPinned(
-      boost::unique_lock<boost::mutex>* client_lock, ClientHandle* client, Page* page);
+      std::unique_lock<std::mutex>* client_lock, ClientHandle* client, Page* page);
 
   /// Same as DebugString() except the caller must already hold 'lock_'.
   std::string DebugStringLocked();
@@ -360,7 +359,7 @@ class BufferPool::Client {
   int debug_write_delay_ms_;
 
   /// Lock to protect the below member variables;
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Condition variable signalled when a write for this client completes.
   ConditionVariable write_complete_cv_;
diff --git a/be/src/runtime/bufferpool/buffer-pool.cc b/be/src/runtime/bufferpool/buffer-pool.cc
index 70f3437..9636c21 100644
--- a/be/src/runtime/bufferpool/buffer-pool.cc
+++ b/be/src/runtime/bufferpool/buffer-pool.cc
@@ -438,7 +438,7 @@ BufferPool::Page* BufferPool::Client::CreatePinnedPage(BufferHandle&& buffer) {
   page->buffer = move(buffer);
   page->pin_count = 1;
 
-  boost::lock_guard<boost::mutex> lock(lock_);
+  std::lock_guard<std::mutex> lock(lock_);
   // The buffer is transferred to the page so will be accounted for in
   // pinned_pages_.bytes() instead of buffers_allocated_bytes_.
   buffers_allocated_bytes_ -= page->len;
diff --git a/be/src/runtime/bufferpool/buffer-pool.h b/be/src/runtime/bufferpool/buffer-pool.h
index 43f457e..7d44905 100644
--- a/be/src/runtime/bufferpool/buffer-pool.h
+++ b/be/src/runtime/bufferpool/buffer-pool.h
@@ -22,7 +22,6 @@
 #include <string>
 #include <vector>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/locks.hpp>
 
 #include "common/atomic.h"
 #include "common/compiler-util.h"
diff --git a/be/src/runtime/bufferpool/free-list.h b/be/src/runtime/bufferpool/free-list.h
index 7d59649..355ece9 100644
--- a/be/src/runtime/bufferpool/free-list.h
+++ b/be/src/runtime/bufferpool/free-list.h
@@ -22,8 +22,6 @@
 #include <cstdint>
 #include <vector>
 
-#include <boost/thread/locks.hpp>
-
 #include "common/logging.h"
 #include "gutil/macros.h"
 #include "runtime/bufferpool/buffer-pool.h"
diff --git a/be/src/runtime/bufferpool/reservation-tracker.cc b/be/src/runtime/bufferpool/reservation-tracker.cc
index 433ca46..3a7107d 100644
--- a/be/src/runtime/bufferpool/reservation-tracker.cc
+++ b/be/src/runtime/bufferpool/reservation-tracker.cc
@@ -19,6 +19,7 @@
 
 #include <algorithm>
 #include <cstdlib>
+#include <mutex>
 
 #include "common/object-pool.h"
 #include "gutil/atomicops.h"
diff --git a/be/src/runtime/bufferpool/reservation-tracker.h b/be/src/runtime/bufferpool/reservation-tracker.h
index 88bd3e6..4da8de7 100644
--- a/be/src/runtime/bufferpool/reservation-tracker.h
+++ b/be/src/runtime/bufferpool/reservation-tracker.h
@@ -20,7 +20,6 @@
 
 #include <stdint.h>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/locks.hpp>
 #include <string>
 
 #include "common/status.h"
diff --git a/be/src/runtime/client-cache.h b/be/src/runtime/client-cache.h
index 191b578..2c6a089 100644
--- a/be/src/runtime/client-cache.h
+++ b/be/src/runtime/client-cache.h
@@ -18,10 +18,10 @@
 #pragma once
 
 #include <list>
+#include <mutex>
 #include <string>
 #include <vector>
 #include <boost/bind.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 #include <gutil/strings/substitute.h>
 
@@ -143,14 +143,14 @@ class ClientCacheHelper {
   /// until they are released for the first time.
   struct PerHostCache {
     /// Protects clients.
-    boost::mutex lock;
+    std::mutex lock;
 
     /// List of client keys for this entry's host.
     std::list<ClientKey> clients;
   };
 
   /// Protects per_host_caches_
-  boost::mutex cache_lock_;
+  std::mutex cache_lock_;
 
   /// Map from an address to a PerHostCache containing a list of keys that have entries in
   /// client_map_ for that host. The value type is wrapped in a shared_ptr so that the
@@ -160,7 +160,7 @@ class ClientCacheHelper {
   PerHostCacheMap per_host_caches_;
 
   /// Protects client_map_.
-  boost::mutex client_map_lock_;
+  std::mutex client_map_lock_;
 
   /// Map from client key back to its associated ThriftClientImpl transport. This is where
   /// all the clients are actually stored, and client instances are owned by this class
diff --git a/be/src/runtime/coordinator-backend-state.cc b/be/src/runtime/coordinator-backend-state.cc
index 825732b..b5e8452 100644
--- a/be/src/runtime/coordinator-backend-state.cc
+++ b/be/src/runtime/coordinator-backend-state.cc
@@ -372,7 +372,7 @@ bool Coordinator::BackendState::IsDone() {
 }
 
 inline bool Coordinator::BackendState::IsDoneLocked(
-    const unique_lock<boost::mutex>& lock) const {
+    const unique_lock<std::mutex>& lock) const {
   DCHECK(lock.owns_lock() && lock.mutex() == &lock_);
   return num_remaining_instances_ == 0 || !status_.ok();
 }
diff --git a/be/src/runtime/coordinator-backend-state.h b/be/src/runtime/coordinator-backend-state.h
index 033c006..1edad2f 100644
--- a/be/src/runtime/coordinator-backend-state.h
+++ b/be/src/runtime/coordinator-backend-state.h
@@ -17,8 +17,9 @@
 
 #pragma once
 
-#include <vector>
+#include <mutex>
 #include <unordered_set>
+#include <vector>
 
 #include <boost/accumulators/accumulators.hpp>
 #include <boost/accumulators/statistics/max.hpp>
@@ -27,7 +28,6 @@
 #include <boost/accumulators/statistics/min.hpp>
 #include <boost/accumulators/statistics/stats.hpp>
 #include <boost/accumulators/statistics/variance.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "gen-cpp/control_service.proxy.h"
 #include "kudu/rpc/rpc_controller.h"
@@ -160,7 +160,7 @@ class Coordinator::BackendState {
   Status exec_rpc_status() const { return exec_rpc_status_; }
 
   int64_t last_report_time_ms() {
-    boost::lock_guard<boost::mutex> l(lock_);
+    std::lock_guard<std::mutex> l(lock_);
     return last_report_time_ms_;
   }
 
@@ -295,7 +295,7 @@ class Coordinator::BackendState {
 
   /// protects fields below
   /// lock ordering: Coordinator::lock_ must only be obtained *prior* to lock_
-  boost::mutex lock_;
+  std::mutex lock_;
 
   // number of in-flight instances
   int num_remaining_instances_ = 0;
@@ -350,7 +350,7 @@ class Coordinator::BackendState {
   void SetExecError(const Status& status);
 
   /// Version of IsDone() where caller must hold lock_ via lock;
-  bool IsDoneLocked(const boost::unique_lock<boost::mutex>& lock) const;
+  bool IsDoneLocked(const std::unique_lock<std::mutex>& lock) const;
 
   /// Same as ComputeResourceUtilization() but caller must hold lock.
   ResourceUtilization ComputeResourceUtilizationLocked();
diff --git a/be/src/runtime/coordinator-filter-state.h b/be/src/runtime/coordinator-filter-state.h
index 9856022..f46f31e 100644
--- a/be/src/runtime/coordinator-filter-state.h
+++ b/be/src/runtime/coordinator-filter-state.h
@@ -19,6 +19,7 @@
 #include <memory>
 #include <utility>
 #include <vector>
+#include <boost/thread/shared_mutex.hpp>
 #include <boost/unordered_set.hpp>
 
 #include "runtime/coordinator.h"
diff --git a/be/src/runtime/coordinator.h b/be/src/runtime/coordinator.h
index 5d57dbf..79e0d7f 100644
--- a/be/src/runtime/coordinator.h
+++ b/be/src/runtime/coordinator.h
@@ -20,7 +20,6 @@
 #include <memory>
 #include <string>
 #include <vector>
-#include <boost/thread/pthread/shared_mutex.hpp>
 #include <boost/unordered_map.hpp>
 #include <rapidjson/document.h>
 
diff --git a/be/src/runtime/dml-exec-state.cc b/be/src/runtime/dml-exec-state.cc
index 4474bae..d66455e 100644
--- a/be/src/runtime/dml-exec-state.cc
+++ b/be/src/runtime/dml-exec-state.cc
@@ -17,8 +17,8 @@
 
 #include "runtime/dml-exec-state.h"
 
-#include <boost/thread/locks.hpp>
-#include <boost/thread/lock_guard.hpp>
+#include <mutex>
+
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/join.hpp>
 #include <boost/filesystem.hpp>
diff --git a/be/src/runtime/dml-exec-state.h b/be/src/runtime/dml-exec-state.h
index c01cf8d..412cf10 100644
--- a/be/src/runtime/dml-exec-state.h
+++ b/be/src/runtime/dml-exec-state.h
@@ -18,8 +18,8 @@
 #pragma once
 
 #include <map>
+#include <mutex>
 #include <string>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 
 #include "common/hdfs.h"
@@ -109,7 +109,7 @@ class DmlExecState {
 
  private:
   /// protects all fields below
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Counts how many rows an DML query has added to a particular partition (partitions
   /// are identified by their partition keys: k1=v1/k2=v2 etc. Unpartitioned tables
diff --git a/be/src/runtime/fragment-instance-state.cc b/be/src/runtime/fragment-instance-state.cc
index 6aa4a86..74b149b 100644
--- a/be/src/runtime/fragment-instance-state.cc
+++ b/be/src/runtime/fragment-instance-state.cc
@@ -19,11 +19,10 @@
 #include "runtime/fragment-instance-state.h"
 
 #include <sstream>
-#include <thrift/protocol/TDebugProtocol.h>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/thread_time.hpp>
-#include <boost/thread/lock_guard.hpp>
+#include <boost/bind.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <thrift/protocol/TDebugProtocol.h>
 
 #include "codegen/llvm-codegen.h"
 #include "exec/exchange-node.h"
diff --git a/be/src/runtime/fragment-instance-state.h b/be/src/runtime/fragment-instance-state.h
index 376faee..921c273 100644
--- a/be/src/runtime/fragment-instance-state.h
+++ b/be/src/runtime/fragment-instance-state.h
@@ -17,9 +17,9 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/atomic.h"
 #include "common/status.h"
diff --git a/be/src/runtime/hbase-table-factory.cc b/be/src/runtime/hbase-table-factory.cc
index 7256fa5..0477e3b 100644
--- a/be/src/runtime/hbase-table-factory.cc
+++ b/be/src/runtime/hbase-table-factory.cc
@@ -17,7 +17,7 @@
 
 #include "runtime/hbase-table-factory.h"
 
-#include <boost/thread/locks.hpp>
+#include <mutex>
 
 #include "common/status.h"
 #include "common/logging.h"
diff --git a/be/src/runtime/hbase-table-factory.h b/be/src/runtime/hbase-table-factory.h
index c0cc7ee..4773957 100644
--- a/be/src/runtime/hbase-table-factory.h
+++ b/be/src/runtime/hbase-table-factory.h
@@ -18,10 +18,12 @@
 #ifndef IMPALA_RUNTIME_HBASE_TABLE_FACTORY_H
 #define IMPALA_RUNTIME_HBASE_TABLE_FACTORY_H
 
-#include <boost/scoped_ptr.hpp>
 #include <jni.h>
+#include <mutex>
 #include <string>
 
+#include <boost/scoped_ptr.hpp>
+
 #include "common/status.h"
 #include "runtime/hbase-table.h"
 
@@ -49,7 +51,7 @@ class HBaseTableFactory {
   /// Connection jobject. Initialized in GetConnection(). The connection_ pointer value
   /// is protected by connection_lock_: the Connection object can be shared between
   /// threads.
-  boost::mutex connection_lock_;
+  std::mutex connection_lock_;
   jobject connection_;
 
   /// Connection class and methods.
diff --git a/be/src/runtime/hbase-table.h b/be/src/runtime/hbase-table.h
index 6c940be..c9ccffb 100644
--- a/be/src/runtime/hbase-table.h
+++ b/be/src/runtime/hbase-table.h
@@ -18,7 +18,6 @@
 #ifndef IMPALA_RUNTIME_HBASE_HTABLE_H_
 #define IMPALA_RUNTIME_HBASE_HTABLE_H_
 
-#include <boost/thread.hpp>
 #include <jni.h>
 #include <string>
 
diff --git a/be/src/runtime/hdfs-fs-cache.cc b/be/src/runtime/hdfs-fs-cache.cc
index 109f675..d3acd0c 100644
--- a/be/src/runtime/hdfs-fs-cache.cc
+++ b/be/src/runtime/hdfs-fs-cache.cc
@@ -17,7 +17,8 @@
 
 #include "runtime/hdfs-fs-cache.h"
 
-#include <boost/thread/locks.hpp>
+#include <mutex>
+
 #include <gutil/strings/substitute.h>
 
 #include "common/logging.h"
diff --git a/be/src/runtime/hdfs-fs-cache.h b/be/src/runtime/hdfs-fs-cache.h
index 8592dc3..9f283b8 100644
--- a/be/src/runtime/hdfs-fs-cache.h
+++ b/be/src/runtime/hdfs-fs-cache.h
@@ -17,9 +17,9 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 #include "common/hdfs.h"
 
@@ -74,7 +74,7 @@ class HdfsFsCache {
   /// Singleton instance. Instantiated in Init().
   static boost::scoped_ptr<HdfsFsCache> instance_;
 
-  boost::mutex lock_;  // protects fs_map_
+  std::mutex lock_; // protects fs_map_
   HdfsFsMap fs_map_;
 
   HdfsFsCache() { }
diff --git a/be/src/runtime/initial-reservations.cc b/be/src/runtime/initial-reservations.cc
index 300f3c2..ed2d1f2 100644
--- a/be/src/runtime/initial-reservations.cc
+++ b/be/src/runtime/initial-reservations.cc
@@ -18,8 +18,8 @@
 #include "runtime/initial-reservations.h"
 
 #include <limits>
+#include <mutex>
 
-#include <boost/thread/pthread/mutex.hpp>
 #include <gflags/gflags.h>
 
 #include "common/logging.h"
diff --git a/be/src/runtime/io/disk-io-mgr-internal.h b/be/src/runtime/io/disk-io-mgr-internal.h
index db176d8..426e406 100644
--- a/be/src/runtime/io/disk-io-mgr-internal.h
+++ b/be/src/runtime/io/disk-io-mgr-internal.h
@@ -19,8 +19,8 @@
 #define IMPALA_RUNTIME_DISK_IO_MGR_INTERNAL_H
 
 #include <unistd.h>
+#include <mutex>
 #include <queue>
-#include <boost/thread/locks.hpp>
 
 #include "common/logging.h"
 #include "runtime/io/request-context.h"
@@ -77,7 +77,7 @@ class DiskQueue {
   /// Enqueue the request context to the disk queue.
   void EnqueueContext(RequestContext* worker) {
     {
-      boost::unique_lock<boost::mutex> disk_lock(lock_);
+      std::unique_lock<std::mutex> disk_lock(lock_);
       // Check that the reader is not already on the queue
       DCHECK(find(request_contexts_.begin(), request_contexts_.end(), worker) ==
           request_contexts_.end());
@@ -122,7 +122,7 @@ class DiskQueue {
   HistogramMetric* read_size_ = nullptr;
 
   /// Lock that protects below members.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Condition variable to signal the disk threads that there is work to do or the
   /// thread should shut down.  A disk thread will be woken up when there is a reader
diff --git a/be/src/runtime/io/disk-io-mgr-stress.cc b/be/src/runtime/io/disk-io-mgr-stress.cc
index 3f0bf6c..96e58b6 100644
--- a/be/src/runtime/io/disk-io-mgr-stress.cc
+++ b/be/src/runtime/io/disk-io-mgr-stress.cc
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 #include "runtime/io/disk-io-mgr-stress.h"
 
@@ -62,7 +62,7 @@ string DiskIoMgrStress::GenerateRandomData() {
 }
 
 struct DiskIoMgrStress::Client {
-  boost::mutex lock;
+  std::mutex lock;
   /// Pool for objects that is cleared when the client is (re-)initialized in NewClient().
   ObjectPool obj_pool;
   unique_ptr<RequestContext> reader;
diff --git a/be/src/runtime/io/disk-io-mgr-stress.h b/be/src/runtime/io/disk-io-mgr-stress.h
index edeaaf2..2eefa92 100644
--- a/be/src/runtime/io/disk-io-mgr-stress.h
+++ b/be/src/runtime/io/disk-io-mgr-stress.h
@@ -22,7 +22,6 @@
 #include <memory>
 #include <vector>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/condition_variable.hpp>
 #include <boost/thread/thread.hpp>
 
 #include "common/object-pool.h"
diff --git a/be/src/runtime/io/disk-io-mgr.h b/be/src/runtime/io/disk-io-mgr.h
index 9e5648a..d2a8047 100644
--- a/be/src/runtime/io/disk-io-mgr.h
+++ b/be/src/runtime/io/disk-io-mgr.h
@@ -21,10 +21,9 @@
 // they are built against.
 #define IMPALA_RUNTIME_IO_DISK_IO_MGR_H
 
+#include <mutex>
 #include <vector>
 
-#include <boost/thread/pthread/mutex.hpp>
-
 #include "common/atomic.h"
 #include "common/hdfs.h"
 #include "common/status.h"
diff --git a/be/src/runtime/io/handle-cache.h b/be/src/runtime/io/handle-cache.h
index 899ef5d..ef751eb 100644
--- a/be/src/runtime/io/handle-cache.h
+++ b/be/src/runtime/io/handle-cache.h
@@ -21,8 +21,7 @@
 #include <list>
 #include <map>
 #include <memory>
-
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 #include "common/hdfs.h"
 #include "common/status.h"
diff --git a/be/src/runtime/io/handle-cache.inline.h b/be/src/runtime/io/handle-cache.inline.h
index 5085c27..66c4cc2 100644
--- a/be/src/runtime/io/handle-cache.inline.h
+++ b/be/src/runtime/io/handle-cache.inline.h
@@ -98,7 +98,7 @@ Status FileHandleCache::GetFileHandle(
   // If this requires a new handle, skip to the creation codepath. Otherwise,
   // find an unused entry with the same mtime
   if (!require_new_handle) {
-    boost::lock_guard<SpinLock> g(p.lock);
+    std::lock_guard<SpinLock> g(p.lock);
     pair<typename MapType::iterator, typename MapType::iterator> range =
       p.cache.equal_range(*fname);
 
@@ -141,7 +141,7 @@ Status FileHandleCache::GetFileHandle(
   // for this file in the multimap. The ordering is largely unimportant if all the
   // existing entries are in use. However, if require_new_handle is true, there may be
   // unused entries, so it would make more sense to insert the new entry at the front.
-  boost::lock_guard<SpinLock> g(p.lock);
+  std::lock_guard<SpinLock> g(p.lock);
   pair<typename MapType::iterator, typename MapType::iterator> range =
       p.cache.equal_range(*fname);
   FileHandleEntry entry(std::move(new_fh), p.lru_list);
@@ -162,7 +162,7 @@ void FileHandleCache::ReleaseFileHandle(std::string* fname,
   // Hash the key and get appropriate partition
   int index = HashUtil::Hash(fname->data(), fname->size(), 0) % cache_partitions_.size();
   FileHandleCachePartition& p = cache_partitions_[index];
-  boost::lock_guard<SpinLock> g(p.lock);
+  std::lock_guard<SpinLock> g(p.lock);
   pair<typename MapType::iterator, typename MapType::iterator> range =
     p.cache.equal_range(*fname);
 
@@ -211,7 +211,7 @@ void FileHandleCache::ReleaseFileHandle(std::string* fname,
 void FileHandleCache::EvictHandlesLoop() {
   while (true) {
     for (FileHandleCachePartition& p : cache_partitions_) {
-      boost::lock_guard<SpinLock> g(p.lock);
+      std::lock_guard<SpinLock> g(p.lock);
       EvictHandles(p);
     }
     // This Get() will time out until shutdown, when the promise is set.
diff --git a/be/src/runtime/io/request-context.cc b/be/src/runtime/io/request-context.cc
index ceb3afe..6c3b356 100644
--- a/be/src/runtime/io/request-context.cc
+++ b/be/src/runtime/io/request-context.cc
@@ -779,8 +779,7 @@ void RequestContext::IncrementDiskThreadAfterDequeue(int disk_id) {
   disk_states_[disk_id].IncrementDiskThreadAfterDequeue();
 }
 
-void RequestContext::DecrementDiskRefCount(
-    const boost::unique_lock<boost::mutex>& lock) {
+void RequestContext::DecrementDiskRefCount(const std::unique_lock<std::mutex>& lock) {
   DCHECK(lock.mutex() == &lock_ && lock.owns_lock());
   DCHECK_GT(num_disks_with_ranges_, 0);
   if (--num_disks_with_ranges_ == 0) {
@@ -790,7 +789,7 @@ void RequestContext::DecrementDiskRefCount(
 }
 
 void RequestContext::ScheduleScanRange(
-    const boost::unique_lock<boost::mutex>& lock, ScanRange* range) {
+    const std::unique_lock<std::mutex>& lock, ScanRange* range) {
   DCHECK(lock.mutex() == &lock_ && lock.owns_lock());
   DCHECK_EQ(state_, Active);
   DCHECK(range != nullptr);
diff --git a/be/src/runtime/io/request-context.h b/be/src/runtime/io/request-context.h
index 9d84cb8..e32c334 100644
--- a/be/src/runtime/io/request-context.h
+++ b/be/src/runtime/io/request-context.h
@@ -147,7 +147,7 @@ class RequestContext {
   void Cancel();
 
   bool IsCancelled() {
-    boost::unique_lock<boost::mutex> lock(lock_);
+    std::unique_lock<std::mutex> lock(lock_);
     return state_ == Cancelled;
   }
 
@@ -253,7 +253,7 @@ class RequestContext {
   /// Decrements the number of active disks for this reader.  If the disk count
   /// goes to 0, the disk complete condition variable is signaled.
   /// 'lock_' must be held via 'lock'.
-  void DecrementDiskRefCount(const boost::unique_lock<boost::mutex>& lock);
+  void DecrementDiskRefCount(const std::unique_lock<std::mutex>& lock);
 
   /// Reader & Disk Scheduling: Readers that currently can't do work are not on
   /// the disk's queue. These readers are ones that don't have any ranges in the
@@ -265,7 +265,7 @@ class RequestContext {
   /// Adds range to in_flight_ranges, scheduling this reader on the disk threads
   /// if necessary.
   /// 'lock_' must be held via 'lock'. Only valid to call if this context is active.
-  void ScheduleScanRange(const boost::unique_lock<boost::mutex>& lock, ScanRange* range);
+  void ScheduleScanRange(const std::unique_lock<std::mutex>& lock, ScanRange* range);
 
   // Called from the disk thread for 'disk_id' to get the next request range to process
   // for this context for the disk. Returns nullptr if there are no ranges currently
@@ -304,26 +304,26 @@ class RequestContext {
   /// client by GetNextUnstartedRange(). If BY_CALLER, the scan range is not added to
   /// any queues. The range will be scheduled later as a separate step, e.g. when it is
   /// unblocked by adding buffers to it. Caller must hold 'lock_' via 'lock'.
-  void AddRangeToDisk(const boost::unique_lock<boost::mutex>& lock, RequestRange* range,
+  void AddRangeToDisk(const std::unique_lock<std::mutex>& lock, RequestRange* range,
       ScheduleMode schedule_mode);
 
   /// Adds an active range to 'active_scan_ranges_'
   void AddActiveScanRangeLocked(
-      const boost::unique_lock<boost::mutex>& lock, ScanRange* range);
+      const std::unique_lock<std::mutex>& lock, ScanRange* range);
 
   /// Removes the range from 'active_scan_ranges_'. Called by ScanRange after eos or
   /// cancellation. If calling the Locked version, the caller must hold
   /// 'lock_'. Otherwise the function will acquire 'lock_'.
   void RemoveActiveScanRange(ScanRange* range);
   void RemoveActiveScanRangeLocked(
-      const boost::unique_lock<boost::mutex>& lock, ScanRange* range);
+      const std::unique_lock<std::mutex>& lock, ScanRange* range);
 
   /// Try to read the scan range from the cache. '*read_succeeded' is set to true if the
   /// scan range can be found in the cache, otherwise false.
   /// If '*needs_buffers' is returned as true, the caller must call
   /// AllocateBuffersForRange() to add buffers for the data to be read into before the
   /// range can be scheduled.
-  Status TryReadFromCache(const boost::unique_lock<boost::mutex>& lock, ScanRange* range,
+  Status TryReadFromCache(const std::unique_lock<std::mutex>& lock, ScanRange* range,
       bool* read_succeeded, bool* needs_buffers);
 
   // Counters are updated by other classes - expose to other io:: classes for convenience.
@@ -392,7 +392,7 @@ class RequestContext {
   /// All fields below are accessed by multiple threads and the lock needs to be
   /// taken before accessing them. Must be acquired before ScanRange::lock_ if both
   /// are held simultaneously.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Current state of the reader
   State state_ = Active;
diff --git a/be/src/runtime/io/request-ranges.h b/be/src/runtime/io/request-ranges.h
index 203836a..4445ad9 100644
--- a/be/src/runtime/io/request-ranges.h
+++ b/be/src/runtime/io/request-ranges.h
@@ -20,8 +20,8 @@
 #include <cstdint>
 #include <deque>
 #include <functional>
+#include <mutex>
 
-#include <boost/thread/pthread/mutex.hpp>
 #include <gtest/gtest_prod.h> // for FRIEND_TEST
 
 #include "common/atomic.h"
@@ -339,7 +339,7 @@ class ScanRange : public RequestRange {
   /// If the data is not cached, returns ok() and *read_succeeded is set to false.
   /// Returns a non-ok status if it ran into a non-continuable error.
   /// The reader lock must be held by the caller.
-  Status ReadFromCache(const boost::unique_lock<boost::mutex>& reader_lock,
+  Status ReadFromCache(const std::unique_lock<std::mutex>& reader_lock,
       bool* read_succeeded) WARN_UNUSED_RESULT;
 
   /// Add buffers for the range to read data into and schedule the range if blocked.
@@ -358,7 +358,7 @@ class ScanRange : public RequestRange {
   /// Either ReturnBuffer() or CleanUpBuffer() is called for every BufferDescriptor.
   /// The caller must hold 'lock_' via 'scan_range_lock'.
   /// This function may acquire 'file_reader_->lock()'
-  void CleanUpBuffer(const boost::unique_lock<boost::mutex>& scan_range_lock,
+  void CleanUpBuffer(const std::unique_lock<std::mutex>& scan_range_lock,
       std::unique_ptr<BufferDescriptor> buffer);
 
   /// Same as CleanUpBuffer() except cleans up multiple buffers and caller must not
@@ -414,11 +414,11 @@ class ScanRange : public RequestRange {
   /// 'unused_iomgr_buffer_bytes_'. If 'unused_iomgr_buffers_' is empty, return NULL.
   /// 'lock_' must be held by the caller via 'scan_range_lock'.
   std::unique_ptr<BufferDescriptor> GetUnusedBuffer(
-      const boost::unique_lock<boost::mutex>& scan_range_lock);
+      const std::unique_lock<std::mutex>& scan_range_lock);
 
   /// Clean up all buffers in 'unused_iomgr_buffers_'. Only valid to call when the scan
   /// range is cancelled or at eos. The caller must hold 'lock_' via 'scan_range_lock'.
-  void CleanUpUnusedBuffers(const boost::unique_lock<boost::mutex>& scan_range_lock);
+  void CleanUpUnusedBuffers(const std::unique_lock<std::mutex>& scan_range_lock);
 
   /// Waits for any in-flight read to complete. Called after CancelInternal() to ensure
   /// no more reads will occur for the scan range.
@@ -426,7 +426,7 @@ class ScanRange : public RequestRange {
 
   /// Returns true if no more buffers will be returned to clients in the future,
   /// either because of hitting eosr or cancellation.
-  bool all_buffers_returned(const boost::unique_lock<boost::mutex>& lock) const {
+  bool all_buffers_returned(const std::unique_lock<std::mutex>& lock) const {
     DCHECK(lock.mutex() == &lock_ && lock.owns_lock());
     return !cancel_status_.ok() || (eosr_queued_ && ready_buffers_.empty());
   }
@@ -508,7 +508,7 @@ class ScanRange : public RequestRange {
   /// This lock should not be taken during FileReader::Open()/Read()/Close().
   /// If RequestContext::lock_ and this lock need to be held simultaneously,
   /// RequestContext::lock_ must be taken first.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Buffers to read into, used if the 'external_buffer_tag_' is NO_BUFFER. These are
   /// initially populated when the client calls AllocateBuffersForRange() and
diff --git a/be/src/runtime/io/scan-range.cc b/be/src/runtime/io/scan-range.cc
index cab33d1..d9d566d 100644
--- a/be/src/runtime/io/scan-range.cc
+++ b/be/src/runtime/io/scan-range.cc
@@ -303,8 +303,7 @@ void ScanRange::SetBlockedOnBuffer() {
   blocked_on_buffer_ = true;
 }
 
-void ScanRange::CleanUpBuffer(
-    const boost::unique_lock<boost::mutex>& scan_range_lock,
+void ScanRange::CleanUpBuffer(const unique_lock<mutex>& scan_range_lock,
     unique_ptr<BufferDescriptor> buffer_desc) {
   DCHECK(scan_range_lock.mutex() == &lock_ && scan_range_lock.owns_lock());
   DCHECK(buffer_desc != nullptr);
diff --git a/be/src/runtime/krpc-data-stream-mgr.cc b/be/src/runtime/krpc-data-stream-mgr.cc
index 89cea22..0551a33 100644
--- a/be/src/runtime/krpc-data-stream-mgr.cc
+++ b/be/src/runtime/krpc-data-stream-mgr.cc
@@ -18,9 +18,8 @@
 #include "runtime/krpc-data-stream-mgr.h"
 
 #include <iostream>
+#include <mutex>
 #include <boost/functional/hash.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/thread.hpp>
 
 #include "kudu/rpc/rpc_context.h"
 #include "kudu/util/net/sockaddr.h"
@@ -64,7 +63,7 @@ DEFINE_int32(datastream_service_num_deserialization_threads, 16,
 DEFINE_int32(datastream_service_deserialization_queue_size, 10000,
     "Number of deferred RPC requests that can be enqueued before being processed by a "
     "deserialization thread.");
-using boost::mutex;
+using std::mutex;
 
 namespace impala {
 
diff --git a/be/src/runtime/krpc-data-stream-mgr.h b/be/src/runtime/krpc-data-stream-mgr.h
index 21bf615..af7ff2c 100644
--- a/be/src/runtime/krpc-data-stream-mgr.h
+++ b/be/src/runtime/krpc-data-stream-mgr.h
@@ -18,10 +18,9 @@
 #pragma once
 
 #include <list>
+#include <mutex>
 #include <queue>
 #include <set>
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 #include <boost/unordered_set.hpp>
 
@@ -340,7 +339,7 @@ class KrpcDataStreamMgr : public CacheLineAligned {
   IntCounter* num_senders_timedout_;
 
   /// protects all fields below
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Map from hash value of fragment instance id/node id pair to stream receivers;
   /// Ownership of the stream revcr is shared between this instance and the caller of
diff --git a/be/src/runtime/krpc-data-stream-recvr.cc b/be/src/runtime/krpc-data-stream-recvr.cc
index 6368ce3..43a13e4 100644
--- a/be/src/runtime/krpc-data-stream-recvr.cc
+++ b/be/src/runtime/krpc-data-stream-recvr.cc
@@ -18,11 +18,9 @@
 #include "runtime/krpc-data-stream-recvr.h"
 
 #include <condition_variable>
+#include <mutex>
 #include <queue>
 
-#include <boost/thread/locks.hpp>
-#include <boost/thread/pthread/mutex.hpp>
-
 #include "exec/kudu-util.h"
 #include "kudu/rpc/rpc_context.h"
 #include "kudu/util/monotime.h"
diff --git a/be/src/runtime/krpc-data-stream-recvr.h b/be/src/runtime/krpc-data-stream-recvr.h
index d98a8cd..4d689e5 100644
--- a/be/src/runtime/krpc-data-stream-recvr.h
+++ b/be/src/runtime/krpc-data-stream-recvr.h
@@ -17,8 +17,8 @@
 
 #pragma once
 
+#include <mutex>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/object-pool.h"
 #include "common/status.h"
diff --git a/be/src/runtime/lib-cache.cc b/be/src/runtime/lib-cache.cc
index cb1bc74..c8084eb 100644
--- a/be/src/runtime/lib-cache.cc
+++ b/be/src/runtime/lib-cache.cc
@@ -17,8 +17,9 @@
 
 #include "runtime/lib-cache.h"
 
+#include <mutex>
+
 #include <boost/filesystem.hpp>
-#include <boost/thread/locks.hpp>
 
 #include "codegen/llvm-codegen.h"
 #include "runtime/hdfs-fs-cache.h"
@@ -41,7 +42,7 @@ scoped_ptr<LibCache> LibCache::instance_;
 
 struct LibCacheEntry {
   // Lock protecting all fields in this entry
-  boost::mutex lock;
+  std::mutex lock;
 
   // The number of users that are using this cache entry. If this is
   // a .so, we can't dlclose unless the use_count goes to 0.
diff --git a/be/src/runtime/lib-cache.h b/be/src/runtime/lib-cache.h
index 7630fe1..69a6c77 100644
--- a/be/src/runtime/lib-cache.h
+++ b/be/src/runtime/lib-cache.h
@@ -17,9 +17,9 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 #include <boost/unordered_set.hpp>
 #include "common/atomic.h"
@@ -145,7 +145,7 @@ class LibCache {
 
   /// Protects lib_cache_. For lock ordering, this lock must always be taken before
   /// the per entry lock.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Maps HDFS library path => cache entry.
   /// Entries in the cache need to be explicitly deleted.
@@ -168,13 +168,12 @@ class LibCache {
   /// taken and returned in *entry_lock.
   /// If an error is returned, there will be no entry in lib_cache_ and *entry is NULL.
   Status GetCacheEntry(const std::string& hdfs_lib_file, LibType type, time_t exp_mtime,
-      boost::unique_lock<boost::mutex>* entry_lock, LibCacheEntry** entry);
+      std::unique_lock<std::mutex>* entry_lock, LibCacheEntry** entry);
 
   /// Implementation to get the cache entry for 'hdfs_lib_file'. Errors are returned
   /// without evicting the cache entry if the status is not OK and *entry is not NULL.
   Status GetCacheEntryInternal(const std::string& hdfs_lib_file, LibType type,
-      time_t exp_mtime, boost::unique_lock<boost::mutex>* entry_lock,
-      LibCacheEntry** entry);
+      time_t exp_mtime, std::unique_lock<std::mutex>* entry_lock, LibCacheEntry** entry);
 
   /// Returns iter's cache entry in 'entry' with 'entry_lock' held if entry does not
   /// need to be refreshed.
@@ -190,7 +189,7 @@ class LibCache {
   /// TODO: cleanup this method's interface and how the outputs are used.
   Status RefreshCacheEntry(const std::string& hdfs_lib_file, LibType type,
       time_t exp_mtime, const LibMap::iterator& iter,
-      boost::unique_lock<boost::mutex>* entry_lock, LibCacheEntry** entry);
+      std::unique_lock<std::mutex>* entry_lock, LibCacheEntry** entry);
 
   /// 'hdfs_lib_file' is copied locally and 'entry' is initialized with its contents.
   /// An error is returned if exp_mtime differs from the mtime on the file system.
diff --git a/be/src/runtime/mem-tracker.h b/be/src/runtime/mem-tracker.h
index 7ae3978..a58f2a2 100644
--- a/be/src/runtime/mem-tracker.h
+++ b/be/src/runtime/mem-tracker.h
@@ -20,9 +20,9 @@
 #include <stdint.h>
 #include <map>
 #include <memory>
+#include <mutex>
 #include <queue>
 #include <vector>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 
 #include "common/logging.h"
@@ -416,7 +416,7 @@ class MemTracker {
   }
 
   /// Lock to protect GcMemory(). This prevents many GCs from occurring at once.
-  boost::mutex gc_lock_;
+  std::mutex gc_lock_;
 
   /// True if this is a Query MemTracker returned from CreateQueryMemTracker().
   bool is_query_mem_tracker_ = false;
@@ -520,7 +520,7 @@ class PoolMemTrackerRegistry {
   /// from this map. Protected by 'pool_to_mem_trackers_lock_'
   typedef boost::unordered_map<std::string, std::unique_ptr<MemTracker>> PoolTrackersMap;
   PoolTrackersMap pool_to_mem_trackers_;
-  /// IMPALA-3068: Use SpinLock instead of boost::mutex so that the lock won't
+  /// IMPALA-3068: Use SpinLock instead of std::mutex so that the lock won't
   /// automatically destroy itself as part of process teardown, which could cause races.
   SpinLock pool_to_mem_trackers_lock_;
 };
diff --git a/be/src/runtime/query-state.cc b/be/src/runtime/query-state.cc
index bae2098..a0c6a30 100644
--- a/be/src/runtime/query-state.cc
+++ b/be/src/runtime/query-state.cc
@@ -17,8 +17,7 @@
 
 #include "runtime/query-state.h"
 
-#include <boost/thread/lock_guard.hpp>
-#include <boost/thread/locks.hpp>
+#include <mutex>
 
 #include "common/thread-debug-info.h"
 #include "exec/kudu-util.h"
@@ -355,7 +354,7 @@ void QueryState::ConstructReport(bool instances_started,
   DCHECK(exec_rpc_params_.has_coord_state_idx());
   report->set_coord_state_idx(exec_rpc_params_.coord_state_idx());
   {
-    std::unique_lock<SpinLock> l(status_lock_);
+    unique_lock<SpinLock> l(status_lock_);
     overall_status_.ToProto(report->mutable_overall_status());
     if (IsValidFInstanceId(failed_finstance_id_)) {
       TUniqueIdToUniqueIdPB(failed_finstance_id_, report->mutable_fragment_instance_id());
@@ -516,7 +515,7 @@ int64_t QueryState::GetReportWaitTimeMs() const {
 
 void QueryState::ErrorDuringPrepare(const Status& status, const TUniqueId& finst_id) {
   {
-    std::unique_lock<SpinLock> l(status_lock_);
+    unique_lock<SpinLock> l(status_lock_);
     if (!HasErrorStatus()) {
       overall_status_ = status;
       failed_finstance_id_ = finst_id;
@@ -527,7 +526,7 @@ void QueryState::ErrorDuringPrepare(const Status& status, const TUniqueId& finst
 
 void QueryState::ErrorDuringExecute(const Status& status, const TUniqueId& finst_id) {
   {
-    std::unique_lock<SpinLock> l(status_lock_);
+    unique_lock<SpinLock> l(status_lock_);
     if (!HasErrorStatus()) {
       overall_status_ = status;
       failed_finstance_id_ = finst_id;
diff --git a/be/src/runtime/runtime-filter-bank.cc b/be/src/runtime/runtime-filter-bank.cc
index 6f98360..e2ce451 100644
--- a/be/src/runtime/runtime-filter-bank.cc
+++ b/be/src/runtime/runtime-filter-bank.cc
@@ -50,7 +50,6 @@ using kudu::rpc::RpcContext;
 using kudu::rpc::RpcController;
 using kudu::rpc::RpcSidecar;
 using namespace impala;
-using namespace boost;
 using namespace strings;
 
 DEFINE_double(max_filter_error_rate, 0.75, "(Advanced) The maximum probability of false "
diff --git a/be/src/runtime/runtime-filter-bank.h b/be/src/runtime/runtime-filter-bank.h
index ac031a7..5c06e09 100644
--- a/be/src/runtime/runtime-filter-bank.h
+++ b/be/src/runtime/runtime-filter-bank.h
@@ -18,6 +18,9 @@
 #ifndef IMPALA_RUNTIME_RUNTIME_FILTER_BANK_H
 #define IMPALA_RUNTIME_RUNTIME_FILTER_BANK_H
 
+#include <condition_variable>
+#include <mutex>
+
 #include "codegen/impala-ir.h"
 #include "common/object-pool.h"
 #include "gen-cpp/data_stream_service.pb.h"
@@ -30,9 +33,6 @@
 
 #include <boost/unordered_map.hpp>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/lock_guard.hpp>
-
-#include <condition_variable>
 
 namespace kudu {
 namespace rpc {
@@ -155,7 +155,7 @@ class RuntimeFilterBank {
       const boost::unordered_map<int32_t, int>& produced_filter_counts);
 
   /// Acquire locks for all filters, returning them to the caller.
-  std::vector<boost::unique_lock<SpinLock>> LockAllFilters();
+  std::vector<std::unique_lock<SpinLock>> LockAllFilters();
 
   /// Implementation of Cancel(). All filter locks must be held by caller.
   void CancelLocked();
diff --git a/be/src/runtime/runtime-filter.h b/be/src/runtime/runtime-filter.h
index db1296a..5108f83 100644
--- a/be/src/runtime/runtime-filter.h
+++ b/be/src/runtime/runtime-filter.h
@@ -17,7 +17,7 @@
 
 #pragma once
 
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 #include "runtime/raw-value.h"
 #include "runtime/runtime-filter-bank.h"
@@ -143,7 +143,7 @@ class RuntimeFilter {
   const int64_t filter_size_;
 
   /// Lock to protect 'arrival_cv_'
-  mutable boost::mutex arrival_mutex_;
+  mutable std::mutex arrival_mutex_;
 
   /// Signalled when a filter arrives or the filter is cancelled. Paired with
   /// 'arrival_mutex_'
diff --git a/be/src/runtime/runtime-filter.inline.h b/be/src/runtime/runtime-filter.inline.h
index 7043d25..635b62d 100644
--- a/be/src/runtime/runtime-filter.inline.h
+++ b/be/src/runtime/runtime-filter.inline.h
@@ -21,8 +21,6 @@
 
 #include "runtime/runtime-filter.h"
 
-#include <boost/thread.hpp>
-
 #include "runtime/raw-value.inline.h"
 #include "util/bloom-filter.h"
 #include "util/min-max-filter.h"
diff --git a/be/src/runtime/runtime-state.cc b/be/src/runtime/runtime-state.cc
index 56c36f7..ac9935c 100644
--- a/be/src/runtime/runtime-state.cc
+++ b/be/src/runtime/runtime-state.cc
@@ -316,7 +316,7 @@ void RuntimeState::ReleaseResources() {
 }
 
 void RuntimeState::SetRPCErrorInfo(TNetworkAddress dest_node, int16_t posix_error_code) {
-  boost::lock_guard<SpinLock> l(aux_error_info_lock_);
+  std::lock_guard<SpinLock> l(aux_error_info_lock_);
   if (aux_error_info_ == nullptr && !reported_aux_error_info_) {
     aux_error_info_.reset(new AuxErrorInfoPB());
     RPCErrorInfoPB* rpc_error_info = aux_error_info_->mutable_rpc_error_info();
@@ -328,7 +328,7 @@ void RuntimeState::SetRPCErrorInfo(TNetworkAddress dest_node, int16_t posix_erro
 }
 
 void RuntimeState::GetUnreportedAuxErrorInfo(AuxErrorInfoPB* aux_error_info) {
-  boost::lock_guard<SpinLock> l(aux_error_info_lock_);
+  std::lock_guard<SpinLock> l(aux_error_info_lock_);
   if (aux_error_info_ != nullptr) {
     aux_error_info->CopyFrom(*aux_error_info_);
   }
diff --git a/be/src/runtime/runtime-state.h b/be/src/runtime/runtime-state.h
index f69a62a..007836c 100644
--- a/be/src/runtime/runtime-state.h
+++ b/be/src/runtime/runtime-state.h
@@ -199,7 +199,7 @@ class RuntimeState {
   inline Status GetQueryStatus() {
     // Do a racy check for query_status_ to avoid unnecessary spinlock acquisition.
     if (UNLIKELY(!query_status_.ok())) {
-      boost::lock_guard<SpinLock> l(query_status_lock_);
+      std::lock_guard<SpinLock> l(query_status_lock_);
       return query_status_;
     }
     return Status::OK();
@@ -213,13 +213,13 @@ class RuntimeState {
 
   /// Returns true if the error log has not reached max_errors_.
   bool LogHasSpace() {
-    boost::lock_guard<SpinLock> l(error_log_lock_);
+    std::lock_guard<SpinLock> l(error_log_lock_);
     return error_log_.size() < query_options().max_errors;
   }
 
   /// Returns true if there are entries in the error log.
   bool HasErrors() {
-    boost::lock_guard<SpinLock> l(error_log_lock_);
+    std::lock_guard<SpinLock> l(error_log_lock_);
     return !error_log_.empty();
   }
 
@@ -275,7 +275,7 @@ class RuntimeState {
 
   /// Sets query_status_ with err_msg if no error has been set yet.
   void SetQueryStatus(const std::string& err_msg) {
-    boost::lock_guard<SpinLock> l(query_status_lock_);
+    std::lock_guard<SpinLock> l(query_status_lock_);
     if (!query_status_.ok()) return;
     query_status_ = Status(err_msg);
   }
@@ -323,7 +323,7 @@ class RuntimeState {
   /// Returns true if this RuntimeState has any auxiliary error information, false
   /// otherwise. Currently, only SetRPCErrorInfo() sets aux error info.
   bool HasAuxErrorInfo() {
-    boost::lock_guard<SpinLock> l(aux_error_info_lock_);
+    std::lock_guard<SpinLock> l(aux_error_info_lock_);
     return aux_error_info_ != nullptr;
   }
 
diff --git a/be/src/runtime/scanner-mem-limiter.cc b/be/src/runtime/scanner-mem-limiter.cc
index 99976d2..dbdd196 100644
--- a/be/src/runtime/scanner-mem-limiter.cc
+++ b/be/src/runtime/scanner-mem-limiter.cc
@@ -17,7 +17,7 @@
 
 #include "runtime/scanner-mem-limiter.h"
 
-#include <boost/thread/locks.hpp>
+#include <mutex>
 
 #include "exec/scan-node.h"
 #include "runtime/mem-tracker.h"
diff --git a/be/src/runtime/sorted-run-merger.h b/be/src/runtime/sorted-run-merger.h
index 1bf4485..7170e8f 100644
--- a/be/src/runtime/sorted-run-merger.h
+++ b/be/src/runtime/sorted-run-merger.h
@@ -17,8 +17,8 @@
 
 #pragma once
 
+#include <mutex>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/object-pool.h"
 #include "util/tuple-row-compare.h"
diff --git a/be/src/runtime/sorter.cc b/be/src/runtime/sorter.cc
index 7b4e3c2..e2f7a76 100644
--- a/be/src/runtime/sorter.cc
+++ b/be/src/runtime/sorter.cc
@@ -17,6 +17,7 @@
 
 #include "runtime/sorter-internal.h"
 
+#include <boost/bind.hpp>
 #include <boost/random/mersenne_twister.hpp>
 #include <boost/random/uniform_int.hpp>
 #include <gutil/strings/substitute.h>
diff --git a/be/src/runtime/thread-resource-mgr.cc b/be/src/runtime/thread-resource-mgr.cc
index a328d5e..48ec598 100644
--- a/be/src/runtime/thread-resource-mgr.cc
+++ b/be/src/runtime/thread-resource-mgr.cc
@@ -17,10 +17,10 @@
 
 #include "runtime/thread-resource-mgr.h"
 
+#include <mutex>
 #include <vector>
 
 #include <boost/algorithm/string.hpp>
-#include <boost/thread/locks.hpp>
 #include <gflags/gflags.h>
 
 #include "common/logging.h"
diff --git a/be/src/runtime/thread-resource-mgr.h b/be/src/runtime/thread-resource-mgr.h
index d8dc6fc..e0f6516 100644
--- a/be/src/runtime/thread-resource-mgr.h
+++ b/be/src/runtime/thread-resource-mgr.h
@@ -19,8 +19,8 @@
 
 #include <stdlib.h>
 
+#include <mutex>
 #include <boost/function.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include <list>
 
@@ -85,7 +85,7 @@ class ThreadResourceMgr {
 
   /// Lock for the entire object. Protects all fields below. Must be acquired before
   /// ThreadResourcePool::lock_ if both are held at the same time.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Pools currently being managed
   typedef std::set<ThreadResourcePool*> Pools;
@@ -218,7 +218,7 @@ class ThreadResourcePool {
 
   /// Lock for the fields below. This lock is taken when the callback function is called.
   /// Must be acquired after ThreadResourceMgr::lock_ if both are held at the same time.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// A vector of registered callback functions. Entries will be set to "empty" function
   /// objects, which can be constructed with the default ThreadAvailableCb() constructor,
diff --git a/be/src/runtime/tmp-file-mgr-test.cc b/be/src/runtime/tmp-file-mgr-test.cc
index 075ee75..70a59f2 100644
--- a/be/src/runtime/tmp-file-mgr-test.cc
+++ b/be/src/runtime/tmp-file-mgr-test.cc
@@ -18,11 +18,11 @@
 #include <cstdio>
 #include <cstdlib>
 #include <limits>
+#include <mutex>
 #include <numeric>
 
 #include <boost/filesystem.hpp>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/locks.hpp>
 #include <gtest/gtest.h>
 
 #include "common/init.h"
diff --git a/be/src/runtime/tmp-file-mgr.cc b/be/src/runtime/tmp-file-mgr.cc
index b803a55..bf227dc 100644
--- a/be/src/runtime/tmp-file-mgr.cc
+++ b/be/src/runtime/tmp-file-mgr.cc
@@ -18,11 +18,11 @@
 #include "runtime/tmp-file-mgr.h"
 
 #include <limits>
+#include <mutex>
 
 #include <boost/algorithm/string.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/lexical_cast.hpp>
-#include <boost/thread/locks.hpp>
 #include <boost/uuid/random_generator.hpp>
 #include <boost/uuid/uuid_io.hpp>
 #include <gutil/strings/join.h>
diff --git a/be/src/runtime/tmp-file-mgr.h b/be/src/runtime/tmp-file-mgr.h
index 0630b04..2599a07 100644
--- a/be/src/runtime/tmp-file-mgr.h
+++ b/be/src/runtime/tmp-file-mgr.h
@@ -21,8 +21,8 @@
 #include <memory>
 #include <utility>
 
+#include <mutex>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/object-pool.h"
 #include "common/status.h"
@@ -387,7 +387,7 @@ class TmpFileMgr {
     /// invalid to call WriteRange/FileGroup methods concurrently from multiple threads,
     /// so no locking is required. This is a terminal lock and should not be held while
     /// acquiring other locks or invoking 'cb_'.
-    boost::mutex write_state_lock_;
+    std::mutex write_state_lock_;
 
     /// True if the the write has been cancelled (but is not necessarily complete).
     bool is_cancelled_;
diff --git a/be/src/scheduling/admission-controller.cc b/be/src/scheduling/admission-controller.cc
index 798abb4..96b6496 100644
--- a/be/src/scheduling/admission-controller.cc
+++ b/be/src/scheduling/admission-controller.cc
@@ -36,6 +36,7 @@
 #include "util/metrics.h"
 #include "util/pretty-printer.h"
 #include "util/runtime-profile-counters.h"
+#include "util/thread.h"
 #include "util/time.h"
 
 #include "common/names.h"
diff --git a/be/src/scheduling/admission-controller.h b/be/src/scheduling/admission-controller.h
index 3b93d3f..07c73cc 100644
--- a/be/src/scheduling/admission-controller.h
+++ b/be/src/scheduling/admission-controller.h
@@ -35,11 +35,11 @@
 #include "util/condition-variable.h"
 #include "util/internal-queue.h"
 #include "util/runtime-profile.h"
-#include "util/thread.h"
 
 namespace impala {
 
 class ExecEnv;
+class Thread;
 
 /// Represents the admission outcome of a query. It is stored in the 'admit_outcome'
 /// input variable passed to AdmissionController::AdmitQuery() if an admission decision
@@ -440,7 +440,7 @@ class AdmissionController {
   ThriftSerializer thrift_serializer_;
 
   /// Protects all access to all variables below.
-  boost::mutex admission_ctrl_lock_;
+  std::mutex admission_ctrl_lock_;
 
   /// The last time a topic update was processed. Time is obtained from
   /// MonotonicMillis(), or is 0 if an update was never received.
diff --git a/be/src/scheduling/cluster-membership-mgr.h b/be/src/scheduling/cluster-membership-mgr.h
index 8305b13..c2e3b5f 100644
--- a/be/src/scheduling/cluster-membership-mgr.h
+++ b/be/src/scheduling/cluster-membership-mgr.h
@@ -210,7 +210,7 @@ class ClusterMembershipMgr {
   /// Ensures that only one thread is processing a membership update at a time, either
   /// from a statestore update or a blacklisting decision. Must be taken before any other
   /// locks in this class.
-  boost::mutex update_membership_lock_;
+  std::mutex update_membership_lock_;
 
   /// Membership metrics
   IntCounter* total_live_executor_groups_ = nullptr;
@@ -225,7 +225,7 @@ class ClusterMembershipMgr {
 
   /// Protects current_membership_. Cannot be held at the same time as
   /// 'callback_fn_lock_'.
-  mutable boost::mutex current_membership_lock_;
+  mutable std::mutex current_membership_lock_;
 
   /// A temporary membership snapshot to hold updates while the statestore is in its
   /// post-recovery grace period. Not exposed to clients. Protected by
@@ -252,7 +252,7 @@ class ClusterMembershipMgr {
 
   /// Protects the callbacks. Cannot be held at the same time as
   /// 'current_membership_lock_'.
-  mutable boost::mutex callback_fn_lock_;
+  mutable std::mutex callback_fn_lock_;
 
   friend class impala::test::SchedulerWrapper;
 };
diff --git a/be/src/scheduling/scheduler.h b/be/src/scheduling/scheduler.h
index 76c30a5..b5910c3 100644
--- a/be/src/scheduling/scheduler.h
+++ b/be/src/scheduling/scheduler.h
@@ -18,10 +18,10 @@
 #pragma once
 
 #include <list>
+#include <mutex>
 #include <string>
 #include <vector>
 #include <boost/heap/binomial_heap.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_map.hpp>
 #include <gtest/gtest_prod.h> // for FRIEND_TEST
 
diff --git a/be/src/service/child-query.h b/be/src/service/child-query.h
index 3447af0..843f8b1 100644
--- a/be/src/service/child-query.h
+++ b/be/src/service/child-query.h
@@ -17,8 +17,8 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/status.h"
 #include "impala-server.h"
@@ -63,7 +63,7 @@ class ChildQuery {
   }
 
   /// Allow child queries to be added to std collections.
-  /// (boost::mutex's operator= and copy c'tor are private)
+  /// (std::mutex's operator= and copy c'tor are private)
   ChildQuery(const ChildQuery& other)
     : query_(other.query_),
       parent_request_state_(other.parent_request_state_),
@@ -74,7 +74,7 @@ class ChildQuery {
       is_cancelled_(other.is_cancelled_) {}
 
   /// Allow child queries to be added to std collections.
-  /// (boost::mutex's operator= and copy c'tor are private)
+  /// (std::mutex's operator= and copy c'tor are private)
   ChildQuery& operator=(const ChildQuery& other) {
     query_ = other.query_;
     parent_request_state_ = other.parent_request_state_;
@@ -139,7 +139,7 @@ class ChildQuery {
   apache::hive::service::cli::thrift::TOperationHandle hs2_handle_;
 
   /// Protects is_running_ and is_cancelled_ to ensure idempotent cancellations.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Indicates whether this query is running. False if the query has not started yet
   /// or if the query has finished either successfully or because of an error.
diff --git a/be/src/service/client-request-state.h b/be/src/service/client-request-state.h
index 8c8afc1..5a4fa1e 100644
--- a/be/src/service/client-request-state.h
+++ b/be/src/service/client-request-state.h
@@ -31,7 +31,6 @@
 #include "gen-cpp/Frontend_types.h"
 #include "gen-cpp/ImpalaHiveServer2Service.h"
 
-#include <boost/thread.hpp>
 #include <boost/unordered_set.hpp>
 #include <vector>
 
@@ -45,6 +44,7 @@ class Frontend;
 class ReportExecStatusRequestPB;
 class RowBatch;
 class RuntimeState;
+class Thread;
 class TRuntimeProfileTree;
 class TupleRow;
 enum class AdmissionOutcome;
@@ -250,8 +250,8 @@ class ClientRequestState {
   TDdlType::type ddl_type() const {
     return exec_request_.catalog_op_request.ddl_params.ddl_type;
   }
-  boost::mutex* lock() { return &lock_; }
-  boost::mutex* fetch_rows_lock() { return &fetch_rows_lock_; }
+  std::mutex* lock() { return &lock_; }
+  std::mutex* fetch_rows_lock() { return &fetch_rows_lock_; }
   /// ExecState is stored using an AtomicEnum, so reads do not require holding lock_.
   ExecState exec_state() const { return exec_state_.Load(); }
   /// Translate exec_state_ to a TOperationState.
@@ -279,23 +279,23 @@ class ClientRequestState {
   }
 
   inline int64_t last_active_ms() const {
-    boost::lock_guard<boost::mutex> l(expiration_data_lock_);
+    std::lock_guard<std::mutex> l(expiration_data_lock_);
     return last_active_time_ms_;
   }
 
   /// Returns true if Impala is actively processing this query.
   inline bool is_active() const {
-    boost::lock_guard<boost::mutex> l(expiration_data_lock_);
+    std::lock_guard<std::mutex> l(expiration_data_lock_);
     return ref_count_ > 0;
   }
 
   bool is_expired() const {
-    boost::lock_guard<boost::mutex> l(expiration_data_lock_);
+    std::lock_guard<std::mutex> l(expiration_data_lock_);
     return is_expired_;
   }
 
   void set_expired() {
-    boost::lock_guard<boost::mutex> l(expiration_data_lock_);
+    std::lock_guard<std::mutex> l(expiration_data_lock_);
     is_expired_ = true;
   }
 
@@ -328,11 +328,11 @@ protected:
   /// while acquiring this lock (since FetchRows() will release and re-acquire lock_ during
   /// its execution).
   /// See "Locking" in the class comment for lock acquisition order.
-  boost::mutex fetch_rows_lock_;
+  std::mutex fetch_rows_lock_;
 
   /// Protects last_active_time_ms_, ref_count_ and is_expired_. Only held during short
   /// function calls - no other locks should be acquired while holding this lock.
-  mutable boost::mutex expiration_data_lock_;
+  mutable std::mutex expiration_data_lock_;
 
   /// Stores the last time that the query was actively doing work, in Unix milliseconds.
   int64_t last_active_time_ms_;
@@ -363,7 +363,7 @@ protected:
   /// requests for this query, e.g. query status and cancellation. Furthermore, until
   /// IMPALA-3882 is fixed, it can indirectly block progress on all other queries.
   /// See "Locking" in the class comment for lock acquisition order.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// TODO: remove and use ExecEnv::GetInstance() instead
   ExecEnv* exec_env_;
diff --git a/be/src/service/impala-hs2-server.cc b/be/src/service/impala-hs2-server.cc
index f355274..6702f30 100644
--- a/be/src/service/impala-hs2-server.cc
+++ b/be/src/service/impala-hs2-server.cc
@@ -1069,11 +1069,11 @@ void ImpalaServer::AddSessionToConnection(
     const TUniqueId& session_id, SessionState* session) {
   const TUniqueId& connection_id = ThriftServer::GetThreadConnectionId();
   {
-    boost::lock_guard<boost::mutex> l(connection_to_sessions_map_lock_);
+    lock_guard<mutex> l(connection_to_sessions_map_lock_);
     connection_to_sessions_map_[connection_id].insert(session_id);
   }
 
-  boost::lock_guard<boost::mutex> session_lock(session->lock);
+  std::lock_guard<std::mutex> session_lock(session->lock);
   if (session->connections.empty()) {
     // This session was previously disconnected but now has an associated
     // connection. It should no longer be considered for the disconnected timeout.
diff --git a/be/src/service/impala-http-handler.cc b/be/src/service/impala-http-handler.cc
index 3c5e2c0..80f5427 100644
--- a/be/src/service/impala-http-handler.cc
+++ b/be/src/service/impala-http-handler.cc
@@ -18,9 +18,9 @@
 #include "service/impala-http-handler.h"
 
 #include <algorithm>
+#include <mutex>
 #include <sstream>
 #include <boost/lexical_cast.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <rapidjson/prettywriter.h>
 #include <rapidjson/stringbuffer.h>
 
diff --git a/be/src/service/impala-server.h b/be/src/service/impala-server.h
index 5fa6f26..3bf95d5 100644
--- a/be/src/service/impala-server.h
+++ b/be/src/service/impala-server.h
@@ -18,11 +18,11 @@
 #pragma once
 
 #include <atomic>
+#include <mutex>
 #include <unordered_map>
 #include <boost/random/random_device.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/unordered_set.hpp>
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_generators.hpp>
@@ -549,7 +549,7 @@ class ImpalaServer : public ImpalaServiceIf,
 
     /// Protects all fields below. See "Locking" in the class comment for lock
     /// acquisition order.
-    boost::mutex lock;
+    std::mutex lock;
 
     /// If true, the session has been closed.
     bool closed;
@@ -1034,7 +1034,7 @@ class ImpalaServer : public ImpalaServiceIf,
   static ThreadSafeRandom rng_;
 
   /// Guards query_log_ and query_log_index_
-  boost::mutex query_log_lock_;
+  std::mutex query_log_lock_;
 
   /// FIFO list of query records, which are written after the query finishes executing
   typedef std::list<QueryStateRecord> QueryLog;
@@ -1080,7 +1080,7 @@ class ImpalaServer : public ImpalaServiceIf,
   std::multiset<int32_t> session_timeout_set_;
 
   /// The lock for protecting the session_timeout_set_.
-  boost::mutex session_timeout_lock_;
+  std::mutex session_timeout_lock_;
 
   /// session_timeout_thread_ relies on the following conditional variable to wake up
   /// when there are sessions that have a timeout.
@@ -1229,7 +1229,7 @@ class ImpalaServer : public ImpalaServiceIf,
 
   /// Protects session_state_map_. See "Locking" in the class comment for lock
   /// acquisition order.
-  boost::mutex session_state_map_lock_;
+  std::mutex session_state_map_lock_;
 
   /// A map from session identifier to a structure containing per-session information
   typedef boost::unordered_map<TUniqueId, std::shared_ptr<SessionState>> SessionStateMap;
@@ -1237,7 +1237,7 @@ class ImpalaServer : public ImpalaServiceIf,
 
   /// Protects connection_to_sessions_map_. See "Locking" in the class comment for lock
   /// acquisition order.
-  boost::mutex connection_to_sessions_map_lock_;
+  std::mutex connection_to_sessions_map_lock_;
 
   /// Map from a connection ID to the associated list of sessions so that all can be
   /// closed when the connection ends. HS2 allows for multiplexing several sessions across
@@ -1258,7 +1258,7 @@ class ImpalaServer : public ImpalaServiceIf,
   /// Decrement the session's reference counter and mark last_accessed_ms so that state
   /// expiration can proceed.
   inline void MarkSessionInactive(std::shared_ptr<SessionState> session) {
-    boost::lock_guard<boost::mutex> l(session->lock);
+    std::lock_guard<std::mutex> l(session->lock);
     DCHECK_GT(session->ref_count, 0);
     --session->ref_count;
     session->last_accessed_ms = UnixMillis();
@@ -1269,7 +1269,7 @@ class ImpalaServer : public ImpalaServiceIf,
   void AddSessionToConnection(const TUniqueId& session_id, SessionState* session);
 
   /// Protects query_locations_. Not held in conjunction with other locks.
-  boost::mutex query_locations_lock_;
+  std::mutex query_locations_lock_;
 
   /// A map from backend to the list of queries currently running or expected to run
   /// there.
@@ -1280,18 +1280,18 @@ class ImpalaServer : public ImpalaServiceIf,
   /// The local backend descriptor. Updated in GetLocalBackendDescriptor() and protected
   /// by 'local_backend_descriptor_lock_';
   std::shared_ptr<const TBackendDescriptor> local_backend_descriptor_;
-  boost::mutex local_backend_descriptor_lock_;
+  std::mutex local_backend_descriptor_lock_;
 
   /// UUID generator for session IDs and secrets. Uses system random device to get
   /// cryptographically secure random numbers.
   boost::uuids::basic_random_generator<boost::random_device> crypto_uuid_generator_;
 
   /// Lock to protect uuid_generator
-  boost::mutex uuid_lock_;
+  std::mutex uuid_lock_;
 
   /// Lock for catalog_update_version_, min_subscriber_catalog_topic_version_,
   /// and catalog_version_update_cv_
-  boost::mutex catalog_version_lock_;
+  std::mutex catalog_version_lock_;
 
   /// Variable to signal when the catalog version has been modified
   ConditionVariable catalog_version_update_cv_;
@@ -1335,7 +1335,7 @@ class ImpalaServer : public ImpalaServiceIf,
 
   /// Guards queries_by_timestamp_. See "Locking" in the class comment for lock
   /// acquisition order.
-  boost::mutex query_expiration_lock_;
+  std::mutex query_expiration_lock_;
 
   enum class ExpirationKind {
     // The query is cancelled if the query has been inactive this long. The event may
diff --git a/be/src/statestore/failure-detector.cc b/be/src/statestore/failure-detector.cc
index 0db5a52..2a6824d 100644
--- a/be/src/statestore/failure-detector.cc
+++ b/be/src/statestore/failure-detector.cc
@@ -17,8 +17,9 @@
 
 #include "statestore/failure-detector.h"
 
+#include <mutex>
+
 #include <boost/assign.hpp>
-#include <boost/thread.hpp>
 
 #include "common/logging.h"
 
diff --git a/be/src/statestore/failure-detector.h b/be/src/statestore/failure-detector.h
index bfc7a52..d44cef8 100644
--- a/be/src/statestore/failure-detector.h
+++ b/be/src/statestore/failure-detector.h
@@ -17,9 +17,9 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/thread/thread_time.hpp>
 
 namespace impala {
@@ -85,7 +85,7 @@ class TimeoutFailureDetector : public FailureDetector {
 
  private:
   /// Protects all members
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Record of last time a successful heartbeat was received
   std::map<std::string, boost::system_time> peer_heartbeat_record_;
@@ -128,7 +128,7 @@ class MissedHeartbeatFailureDetector : public FailureDetector {
   PeerState ComputePeerState(int32_t missed_heatbeat_count);
 
   /// Protects all members
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// The maximum number of heartbeats that can be missed consecutively before a
   /// peer is considered failed.
diff --git a/be/src/statestore/statestore-subscriber.cc b/be/src/statestore/statestore-subscriber.cc
index 0d3070e..0bf46e5 100644
--- a/be/src/statestore/statestore-subscriber.cc
+++ b/be/src/statestore/statestore-subscriber.cc
@@ -17,6 +17,7 @@
 
 #include "statestore/statestore-subscriber.h"
 
+#include <mutex>
 #include <sstream>
 #include <utility>
 
@@ -46,7 +47,6 @@
 using boost::posix_time::seconds;
 using boost::shared_lock;
 using boost::shared_mutex;
-using boost::try_to_lock;
 using std::string;
 
 using namespace apache::thrift;
@@ -397,7 +397,7 @@ Status StatestoreSubscriber::UpdateState(const TopicDeltaMap& incoming_topic_del
   //
   // TODO: Consider returning an error in this case so that the statestore will eventually
   // stop sending updates even if re-registration fails.
-  shared_lock<shared_mutex> l(lock_, try_to_lock);
+  shared_lock<shared_mutex> l(lock_, boost::try_to_lock);
   if (!l.owns_lock()) {
     *skipped = true;
     return Status::OK();
@@ -416,7 +416,7 @@ Status StatestoreSubscriber::UpdateState(const TopicDeltaMap& incoming_topic_del
       continue;
     }
     TopicRegistration& registration = it->second;
-    unique_lock<mutex> ul(registration.update_lock, try_to_lock);
+    unique_lock<mutex> ul(registration.update_lock, std::try_to_lock);
     if (!ul.owns_lock()) {
       // Statestore sent out concurrent topic updates. Avoid blocking the RPC by skipping
       // the topic.
diff --git a/be/src/statestore/statestore-subscriber.h b/be/src/statestore/statestore-subscriber.h
index 051b761..4047b10 100644
--- a/be/src/statestore/statestore-subscriber.h
+++ b/be/src/statestore/statestore-subscriber.h
@@ -17,12 +17,12 @@
 
 #pragma once
 
+#include <mutex>
 #include <string>
 
 #include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
-#include <boost/thread/pthread/shared_mutex.hpp>
+#include <boost/thread/shared_mutex.hpp>
 
 #include "gen-cpp/StatestoreService.h"
 #include "gen-cpp/StatestoreSubscriber.h"
@@ -206,7 +206,7 @@ class StatestoreSubscriber {
 
   /// Protects registration_id_. Must be taken after lock_ if both are to be taken
   /// together.
-  boost::mutex registration_id_lock_;
+  std::mutex registration_id_lock_;
 
   /// Set during Register(), this is the unique ID of the current registration with the
   /// statestore. If this subscriber must recover, or disconnects and then reconnects, the
@@ -222,7 +222,7 @@ class StatestoreSubscriber {
     /// Held when processing a topic update. 'StatestoreSubscriber::lock_' must be held in
     /// shared mode before acquiring this lock. If taking multiple update locks, they must
     /// be acquired in ascending order of topic name.
-    boost::mutex update_lock;
+    std::mutex update_lock;
 
     /// Whether the subscriber considers this topic to be "transient", that is any updates
     /// it makes will be deleted upon failure or disconnection.
diff --git a/be/src/statestore/statestore.cc b/be/src/statestore/statestore.cc
index 07e5243..08f4290 100644
--- a/be/src/statestore/statestore.cc
+++ b/be/src/statestore/statestore.cc
@@ -22,7 +22,6 @@
 #include <utility>
 
 #include <boost/lexical_cast.hpp>
-#include <boost/thread.hpp>
 #include <thrift/Thrift.h>
 #include <gutil/strings/substitute.h>
 #include <gutil/strings/util.h>
diff --git a/be/src/statestore/statestore.h b/be/src/statestore/statestore.h
index 9a26e07..a08d338 100644
--- a/be/src/statestore/statestore.h
+++ b/be/src/statestore/statestore.h
@@ -479,7 +479,7 @@ class Statestore : public CacheLineAligned {
 
     /// Lock held when adding or deleting transient entries. See class comment for lock
     /// acquisition order.
-    boost::mutex transient_entry_lock_;
+    std::mutex transient_entry_lock_;
 
     /// True once DeleteAllTransientEntries() has been called during subscriber
     /// unregisteration. Protected by 'transient_entry_lock_'
@@ -488,7 +488,7 @@ class Statestore : public CacheLineAligned {
 
   /// Protects access to subscribers_ and subscriber_uuid_generator_. See the class
   /// comment for the lock acquisition order.
-  boost::mutex subscribers_lock_;
+  std::mutex subscribers_lock_;
 
   /// Map of subscribers currently connected; upon failure their entry is removed from this
   /// map. Subscribers must only be removed by UnregisterSubscriber() which ensures that
diff --git a/be/src/testutil/impalad-query-executor.h b/be/src/testutil/impalad-query-executor.h
index c50ac33..fa226f4 100644
--- a/be/src/testutil/impalad-query-executor.h
+++ b/be/src/testutil/impalad-query-executor.h
@@ -22,7 +22,6 @@
 #include <string>
 #include <vector>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/thread.hpp>
 
 #include "rpc/thrift-client.h"
 #include "common/status.h"
diff --git a/be/src/transport/TSaslServerTransport.cpp b/be/src/transport/TSaslServerTransport.cpp
index 9bd7795..97548fe 100644
--- a/be/src/transport/TSaslServerTransport.cpp
+++ b/be/src/transport/TSaslServerTransport.cpp
@@ -21,11 +21,10 @@
 #include "config.h"
 #ifdef HAVE_SASL_SASL_H
 #include <stdint.h>
+#include <mutex>
 #include <sstream>
-#include <boost/shared_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/thread.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include <thrift/transport/TBufferTransports.h>
 #include <thrift/transport/TSocket.h>
diff --git a/be/src/transport/TSaslServerTransport.h b/be/src/transport/TSaslServerTransport.h
index f55b119..9edfc21 100644
--- a/be/src/transport/TSaslServerTransport.h
+++ b/be/src/transport/TSaslServerTransport.h
@@ -20,11 +20,11 @@
 
 #pragma once
 
-#include <string>
 #include <pthread.h>
+#include <mutex>
+#include <string>
 
 #include <boost/shared_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <thrift/transport/TTransport.h>
 #include "transport/TSasl.h"
 #include "transport/TSaslTransport.h"
@@ -191,8 +191,7 @@ class TSaslServerTransport : public TSaslTransport {
     TransportMap transportMap_;
 
     /* Lock to synchronize the transport map. */
-    boost::mutex transportMap_mutex_;
-
+    std::mutex transportMap_mutex_;
   };
 
 };
diff --git a/be/src/util/blocking-queue-test.cc b/be/src/util/blocking-queue-test.cc
index 4a78e7e..acc9e35 100644
--- a/be/src/util/blocking-queue-test.cc
+++ b/be/src/util/blocking-queue-test.cc
@@ -16,8 +16,9 @@
 // under the License.
 
 #include <unistd.h>
-#include <boost/thread.hpp>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
+
+#include <boost/thread/thread.hpp>
 #include <glog/logging.h>
 
 #include "testutil/gtest-util.h"
diff --git a/be/src/util/blocking-queue.h b/be/src/util/blocking-queue.h
index d2bc0dd..ae9be42 100644
--- a/be/src/util/blocking-queue.h
+++ b/be/src/util/blocking-queue.h
@@ -20,8 +20,8 @@
 #include <unistd.h>
 #include <deque>
 #include <memory>
+#include <mutex>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/atomic.h"
 #include "common/compiler-util.h"
@@ -86,12 +86,12 @@ class BlockingQueue : public CacheLineAligned {
   /// Returns false if we were shut down prior to getting the element, and there
   /// are no more elements available.
   bool BlockingGet(T* out) {
-    boost::unique_lock<boost::mutex> read_lock(get_lock_);
+    std::unique_lock<std::mutex> read_lock(get_lock_);
 
     if (UNLIKELY(get_list_.empty())) {
       MonotonicStopWatch timer;
       // Block off writers while swapping 'get_list_' with 'put_list_'.
-      boost::unique_lock<boost::mutex> write_lock(put_lock_);
+      std::unique_lock<std::mutex> write_lock(put_lock_);
       while (put_list_.empty()) {
         DCHECK(get_list_.empty());
         if (UNLIKELY(shutdown_)) return false;
@@ -146,7 +146,7 @@ class BlockingQueue : public CacheLineAligned {
     MonotonicStopWatch timer;
     int64_t val_bytes = ElemBytesFn()(val);
     DCHECK_GE(val_bytes, 0);
-    boost::unique_lock<boost::mutex> write_lock(put_lock_);
+    std::unique_lock<std::mutex> write_lock(put_lock_);
     while (!HasCapacityInternal(write_lock, val_bytes) && !shutdown_) {
       if (put_wait_timer_ != nullptr) timer.Start();
       put_cv_.Wait(write_lock);
@@ -173,7 +173,7 @@ class BlockingQueue : public CacheLineAligned {
     MonotonicStopWatch timer;
     int64_t val_bytes = ElemBytesFn()(val);
     DCHECK_GE(val_bytes, 0);
-    boost::unique_lock<boost::mutex> write_lock(put_lock_);
+    std::unique_lock<std::mutex> write_lock(put_lock_);
     timespec abs_time;
     TimeFromNowMicros(timeout_micros, &abs_time);
     bool notified = true;
@@ -202,7 +202,7 @@ class BlockingQueue : public CacheLineAligned {
     {
       // No need to hold 'get_lock_' here. BlockingGet() may sleep with 'get_lock_' so
       // it may delay the caller here if the lock is acquired.
-      boost::lock_guard<boost::mutex> write_lock(put_lock_);
+      std::lock_guard<std::mutex> write_lock(put_lock_);
       shutdown_ = true;
     }
 
@@ -211,18 +211,17 @@ class BlockingQueue : public CacheLineAligned {
   }
 
   uint32_t Size() const {
-    boost::unique_lock<boost::mutex> write_lock(put_lock_);
+    std::unique_lock<std::mutex> write_lock(put_lock_);
     return SizeLocked(write_lock);
   }
 
   bool AtCapacity() const {
-    boost::unique_lock<boost::mutex> write_lock(put_lock_);
+    std::unique_lock<std::mutex> write_lock(put_lock_);
     return SizeLocked(write_lock) >= max_elements_;
   }
 
  private:
-
-  uint32_t ALWAYS_INLINE SizeLocked(const boost::unique_lock<boost::mutex>& lock) const {
+  uint32_t ALWAYS_INLINE SizeLocked(const std::unique_lock<std::mutex>& lock) const {
     // The size of 'get_list_' is read racily to avoid getting 'get_lock_' in write path.
     DCHECK(lock.mutex() == &put_lock_ && lock.owns_lock());
     return get_list_size_.Load() + put_list_.size();
@@ -230,8 +229,7 @@ class BlockingQueue : public CacheLineAligned {
 
   /// Return true if the queue has capacity to add one more element with size 'val_bytes'.
   /// Caller must hold 'put_lock_' via 'lock'.
-  bool HasCapacityInternal(
-      const boost::unique_lock<boost::mutex>& lock, int64_t val_bytes) {
+  bool HasCapacityInternal(const std::unique_lock<std::mutex>& lock, int64_t val_bytes) {
     DCHECK(lock.mutex() == &put_lock_ && lock.owns_lock());
     uint32_t size = SizeLocked(lock);
     if (size >= max_elements_) return false;
@@ -261,7 +259,7 @@ class BlockingQueue : public CacheLineAligned {
 
   /// Guards against concurrent access to 'put_list_'.
   /// Please see comments at the beginning of the file for lock ordering.
-  mutable boost::mutex put_lock_;
+  mutable std::mutex put_lock_;
 
   /// The queue for items enqueued by BlockingPut(). Guarded by 'put_lock_'.
   std::deque<T> put_list_;
@@ -278,7 +276,7 @@ class BlockingQueue : public CacheLineAligned {
   int64_t put_bytes_enqueued_ = 0;
 
   /// Guards against concurrent access to 'get_list_'.
-  mutable boost::mutex get_lock_;
+  mutable std::mutex get_lock_;
 
   /// The queue of items to be consumed by BlockingGet(). Guarded by 'get_lock_'.
   std::deque<T> get_list_;
diff --git a/be/src/util/collection-metrics.h b/be/src/util/collection-metrics.h
index e93b5c9..174d8de 100644
--- a/be/src/util/collection-metrics.h
+++ b/be/src/util/collection-metrics.h
@@ -32,7 +32,6 @@
 #include <boost/accumulators/statistics/min.hpp>
 #include <boost/accumulators/statistics/variance.hpp>
 #include <boost/thread/lock_guard.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "common/logging.h"
 #include "util/metrics-fwd.h"
@@ -60,19 +59,19 @@ class SetMetric : public Metric {
 
   /// Put an item in this set.
   void Add(const T& item) {
-    boost::lock_guard<boost::mutex> l(lock_);
+    std::lock_guard<std::mutex> l(lock_);
     value_.insert(item);
   }
 
   /// Remove an item from this set by value.
   void Remove(const T& item) {
-    boost::lock_guard<boost::mutex> l(lock_);
+    std::lock_guard<std::mutex> l(lock_);
     value_.erase(item);
   }
 
   /// Copy out value.
   std::set<T> value() {
-    boost::lock_guard<boost::mutex> l(lock_);
+    std::lock_guard<std::mutex> l(lock_);
     return value_;
   }
 
@@ -92,7 +91,7 @@ class SetMetric : public Metric {
 
  private:
   /// Lock protecting the set
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// The set of items
   std::set<T> value_;
@@ -120,13 +119,13 @@ class StatsMetric : public Metric {
   }
 
   void Update(const T& value) {
-    boost::lock_guard<boost::mutex> l(lock_);
+    std::lock_guard<std::mutex> l(lock_);
     value_ = value;
     acc_(value);
   }
 
   void Reset() {
-    boost::lock_guard<boost::mutex> l(lock_);
+    std::lock_guard<std::mutex> l(lock_);
     acc_ = Accumulator();
   }
 
@@ -144,7 +143,7 @@ class StatsMetric : public Metric {
   TUnit::type unit_;
 
   /// Lock protecting the value and the accumulator_set
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// The last value
   T value_;
diff --git a/be/src/util/condition-variable.h b/be/src/util/condition-variable.h
index 07d710e..f12031e 100644
--- a/be/src/util/condition-variable.h
+++ b/be/src/util/condition-variable.h
@@ -19,9 +19,8 @@
 
 #include <pthread.h>
 #include <unistd.h>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 #include <boost/thread/pthread/timespec.hpp>
-#include <boost/thread/thread_time.hpp>
 
 #include "util/time.h"
 
@@ -44,7 +43,7 @@ class ConditionVariable {
   ~ConditionVariable() { pthread_cond_destroy(&cv_); }
 
   /// Wait indefinitely on the condition variable until it's notified.
-  void Wait(boost::unique_lock<boost::mutex>& lock) {
+  void Wait(std::unique_lock<std::mutex>& lock) {
     DCHECK(lock.owns_lock());
     pthread_mutex_t* mutex = lock.mutex()->native_handle();
     pthread_cond_wait(&cv_, mutex);
@@ -53,7 +52,7 @@ class ConditionVariable {
   /// Wait until the condition variable is notified or 'abs_time' has passed.
   /// Returns true if the condition variable is notified before the absolute timeout
   /// specified in 'abs_time' has passed. Returns false otherwise.
-  bool WaitUntil(boost::unique_lock<boost::mutex>& lock, const timespec& abs_time) {
+  bool WaitUntil(std::unique_lock<std::mutex>& lock, const timespec& abs_time) {
     DCHECK(lock.owns_lock());
     pthread_mutex_t* mutex = lock.mutex()->native_handle();
     return pthread_cond_timedwait(&cv_, mutex, &abs_time) == 0;
@@ -62,7 +61,7 @@ class ConditionVariable {
   /// Wait until the condition variable is notified or 'duration_us' microseconds
   /// have passed. Returns true if the condition variable is notified in time.
   /// Returns false otherwise.
-  bool WaitFor(boost::unique_lock<boost::mutex>& lock, int64_t duration_us) {
+  bool WaitFor(std::unique_lock<std::mutex>& lock, int64_t duration_us) {
     timespec deadline;
     TimeFromNowMicros(duration_us, &deadline);
     return WaitUntil(lock, deadline);
diff --git a/be/src/util/cyclic-barrier-test.cc b/be/src/util/cyclic-barrier-test.cc
index 6713705..2617263 100644
--- a/be/src/util/cyclic-barrier-test.cc
+++ b/be/src/util/cyclic-barrier-test.cc
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
 
 #include "common/atomic.h"
 #include "testutil/death-test-util.h"
diff --git a/be/src/util/cyclic-barrier.cc b/be/src/util/cyclic-barrier.cc
index 38b9cc0..aed0efd 100644
--- a/be/src/util/cyclic-barrier.cc
+++ b/be/src/util/cyclic-barrier.cc
@@ -17,8 +17,7 @@
 
 #include "util/cyclic-barrier.h"
 
-#include <boost/thread/lock_guard.hpp>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 #include "common/names.h"
 
diff --git a/be/src/util/cyclic-barrier.h b/be/src/util/cyclic-barrier.h
index 0854464..7b2aee5 100644
--- a/be/src/util/cyclic-barrier.h
+++ b/be/src/util/cyclic-barrier.h
@@ -18,9 +18,7 @@
 #pragma once
 
 #include <cstdint>
-
-#include <boost/thread/lock_types.hpp>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 #include "common/logging.h"
 #include "common/status.h"
@@ -44,7 +42,7 @@ class CyclicBarrier {
   template <typename F>
   Status Wait(const F& fn) {
     {
-      boost::unique_lock<boost::mutex> l(lock_);
+      std::unique_lock<std::mutex> l(lock_);
       RETURN_IF_ERROR(cancel_status_);
       ++num_waiting_threads_;
       DCHECK_LE(num_waiting_threads_, num_threads_);
@@ -77,7 +75,7 @@ class CyclicBarrier {
   const int num_threads_;
 
   // Protects below members.
-  boost::mutex lock_;
+  std::mutex lock_;
 
   // Condition variable that is signalled (with NotifyAll) when all threads join the
   // barrier, or the barrier is cancelled.
diff --git a/be/src/util/hdfs-bulk-ops.h b/be/src/util/hdfs-bulk-ops.h
index 9c5308c..729e5df 100644
--- a/be/src/util/hdfs-bulk-ops.h
+++ b/be/src/util/hdfs-bulk-ops.h
@@ -18,8 +18,8 @@
 #ifndef IMPALA_UTIL_HDFS_BULK_OPS_H
 #define IMPALA_UTIL_HDFS_BULK_OPS_H
 
+#include <mutex>
 #include <string>
-#include <boost/thread.hpp>
 
 #include "common/hdfs.h"
 #include "common/atomic.h"
@@ -132,7 +132,7 @@ class HdfsOperationSet {
   HdfsFsCache::HdfsFsMap* connection_cache_;
 
   /// Protects errors_ and abort_on_error_ during Execute
-  boost::mutex errors_lock_;
+  std::mutex errors_lock_;
 
   /// All errors produced during Execute
   Errors errors_;
diff --git a/be/src/util/histogram-metric.h b/be/src/util/histogram-metric.h
index 26d6bb6..2e6ca7f 100644
--- a/be/src/util/histogram-metric.h
+++ b/be/src/util/histogram-metric.h
@@ -42,7 +42,7 @@ class HistogramMetric : public Metric {
       std::stringstream* metric_kind) override;
 
   void Update(int64_t val) {
-    boost::lock_guard<SpinLock> l(lock_);
+    std::lock_guard<SpinLock> l(lock_);
     histogram_->Increment(val);
   }
 
diff --git a/be/src/util/internal-queue-test.cc b/be/src/util/internal-queue-test.cc
index aaa49e0..7bf06ef 100644
--- a/be/src/util/internal-queue-test.cc
+++ b/be/src/util/internal-queue-test.cc
@@ -16,8 +16,9 @@
 // under the License.
 
 #include <unistd.h>
-#include <boost/thread.hpp>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
+
+#include <boost/thread/thread.hpp>
 #include <glog/logging.h>
 #include <gtest/gtest.h>
 
diff --git a/be/src/util/internal-queue.h b/be/src/util/internal-queue.h
index 063dc3a..ed367d7 100644
--- a/be/src/util/internal-queue.h
+++ b/be/src/util/internal-queue.h
@@ -19,8 +19,9 @@
 #ifndef IMPALA_UTIL_INTERNAL_QUEUE_H
 #define IMPALA_UTIL_INTERNAL_QUEUE_H
 
+#include <mutex>
+
 #include <boost/function.hpp>
-#include <boost/thread/locks.hpp>
 
 #include "util/fake-lock.h"
 #include "util/spinlock.h"
@@ -57,11 +58,11 @@ class InternalQueueBase {
 
     /// Returns the Next/Prev node or nullptr if this is the end/front.
     T* Next() const {
-      boost::lock_guard<LockType> lock(parent_queue->lock_);
+      std::lock_guard<LockType> lock(parent_queue->lock_);
       return reinterpret_cast<T*>(next);
     }
     T* Prev() const {
-      boost::lock_guard<LockType> lock(parent_queue->lock_);
+      std::lock_guard<LockType> lock(parent_queue->lock_);
       return reinterpret_cast<T*>(prev);
     }
 
@@ -79,7 +80,7 @@ class InternalQueueBase {
   /// Returns the element at the head of the list without dequeuing or nullptr
   /// if the queue is empty. This is O(1).
   T* head() const {
-    boost::lock_guard<LockType> lock(lock_);
+    std::lock_guard<LockType> lock(lock_);
     if (empty()) return nullptr;
     return reinterpret_cast<T*>(head_);
   }
@@ -87,7 +88,7 @@ class InternalQueueBase {
   /// Returns the element at the end of the list without dequeuing or nullptr
   /// if the queue is empty. This is O(1).
   T* tail() {
-    boost::lock_guard<LockType> lock(lock_);
+    std::lock_guard<LockType> lock(lock_);
     if (empty()) return nullptr;
     return reinterpret_cast<T*>(tail_);
   }
@@ -100,7 +101,7 @@ class InternalQueueBase {
     DCHECK(node->parent_queue == nullptr);
     node->parent_queue = this;
     {
-      boost::lock_guard<LockType> lock(lock_);
+      std::lock_guard<LockType> lock(lock_);
       if (tail_ != nullptr) tail_->next = node;
       node->prev = tail_;
       tail_ = node;
@@ -117,7 +118,7 @@ class InternalQueueBase {
     DCHECK(node->parent_queue == nullptr);
     node->parent_queue = this;
     {
-      boost::lock_guard<LockType> lock(lock_);
+      std::lock_guard<LockType> lock(lock_);
       if (head_ != nullptr) head_->prev = node;
       node->next = head_;
       head_ = node;
@@ -131,7 +132,7 @@ class InternalQueueBase {
   T* Dequeue() {
     Node* result = nullptr;
     {
-      boost::lock_guard<LockType> lock(lock_);
+      std::lock_guard<LockType> lock(lock_);
       if (empty()) return nullptr;
       --size_;
       result = head_;
@@ -153,7 +154,7 @@ class InternalQueueBase {
   T* PopBack() {
     Node* result = nullptr;
     {
-      boost::lock_guard<LockType> lock(lock_);
+      std::lock_guard<LockType> lock(lock_);
       if (empty()) return nullptr;
       --size_;
       result = tail_;
@@ -176,7 +177,7 @@ class InternalQueueBase {
     Node* node = (Node*)n;
     if (node->parent_queue != this) return false;
     {
-      boost::lock_guard<LockType> lock(lock_);
+      std::lock_guard<LockType> lock(lock_);
       if (node->next == nullptr && node->prev == nullptr) {
         // Removing only node
         DCHECK(node == head_);
@@ -210,7 +211,7 @@ class InternalQueueBase {
 
   /// Clears all elements in the list.
   void Clear() {
-    boost::lock_guard<LockType> lock(lock_);
+    std::lock_guard<LockType> lock(lock_);
     Node* cur = head_;
     while (cur != nullptr) {
       Node* tmp = cur;
@@ -233,7 +234,7 @@ class InternalQueueBase {
   /// Validates the internal structure of the list
   bool Validate() {
     int num_elements_found = 0;
-    boost::lock_guard<LockType> lock(lock_);
+    std::lock_guard<LockType> lock(lock_);
     if (head_ == nullptr) {
       if (tail_ != nullptr) return false;
       if (size() != 0) return false;
@@ -261,7 +262,7 @@ class InternalQueueBase {
   // false, terminate iteration. It is invalid to call other InternalQueue methods
   // from 'fn'.
   void Iterate(boost::function<bool(T*)> fn) {
-    boost::lock_guard<LockType> lock(lock_);
+    std::lock_guard<LockType> lock(lock_);
     for (Node* current = head_; current != nullptr; current = current->next) {
       if (!fn(reinterpret_cast<T*>(current))) return;
     }
@@ -272,7 +273,7 @@ class InternalQueueBase {
     std::stringstream ss;
     ss << "(";
     {
-      boost::lock_guard<LockType> lock(lock_);
+      std::lock_guard<LockType> lock(lock_);
       Node* curr = head_;
       while (curr != nullptr) {
         ss << (void*)curr;
diff --git a/be/src/util/memory-metrics.cc b/be/src/util/memory-metrics.cc
index fb4a52a..ccfc6b5 100644
--- a/be/src/util/memory-metrics.cc
+++ b/be/src/util/memory-metrics.cc
@@ -29,7 +29,7 @@
 #include "util/time.h"
 
 using boost::algorithm::to_lower;
-using boost::lock_guard;
+using std::lock_guard;
 using namespace impala;
 using namespace strings;
 
@@ -264,14 +264,14 @@ void JvmMetricCache::GrabMetricsIfNecessary() {
 
 int64_t JvmMetricCache::GetCounterMetric(
     int64_t(*accessor)(const TGetJvmMemoryMetricsResponse&)) {
-  lock_guard<boost::mutex> lock_guard(lock_);
+  lock_guard<std::mutex> lock_guard(lock_);
   GrabMetricsIfNecessary();
   return accessor(last_response_);
 }
 
 int64_t JvmMetricCache::GetPoolMetric(const std::string& mempool_name,
     JvmMemoryMetricType type) {
-  lock_guard<boost::mutex> lock_guard(lock_);
+  lock_guard<std::mutex> lock_guard(lock_);
   GrabMetricsIfNecessary();
 
   for (const TJvmMemoryPool& pool : last_response_.memory_pools) {
@@ -303,7 +303,7 @@ int64_t JvmMetricCache::GetPoolMetric(const std::string& mempool_name,
 }
 
 vector<string> JvmMetricCache::GetPoolNames() {
-  lock_guard<boost::mutex> lock_guard(lock_);
+  lock_guard<std::mutex> lock_guard(lock_);
   GrabMetricsIfNecessary();
   vector<string> names;
   for (const TJvmMemoryPool& usage: last_response_.memory_pools) {
diff --git a/be/src/util/memory-metrics.h b/be/src/util/memory-metrics.h
index 9dc9eab..b1efdcc 100644
--- a/be/src/util/memory-metrics.h
+++ b/be/src/util/memory-metrics.h
@@ -19,8 +19,8 @@
 
 #include "util/metrics.h"
 
+#include <mutex>
 #include <boost/bind.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <gperftools/malloc_extension.h>
 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
 #include <sanitizer/allocator_interface.h>
@@ -184,7 +184,7 @@ class JvmMetricCache {
     /// Updates metrics if over CACHE_PERIOD_MILLIS has elapsed.
     void GrabMetricsIfNecessary();
 
-    boost::mutex lock_;
+    std::mutex lock_;
     /// Time when metrics were last fetched, using MonotonicMillis().
     /// Protected by lock_.
     int64_t last_fetch_ = 0;
diff --git a/be/src/util/metrics.h b/be/src/util/metrics.h
index a2b174d..65af37f 100644
--- a/be/src/util/metrics.h
+++ b/be/src/util/metrics.h
@@ -19,11 +19,11 @@
 
 #include <iosfwd>
 #include <map>
+#include <mutex>
 #include <string>
 #include <vector>
 #include <boost/function.hpp>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/locks.hpp>
 #include <gtest/gtest_prod.h> // for FRIEND_TEST
 #include <rapidjson/fwd.h>
 
@@ -186,13 +186,13 @@ class LockedMetric : public ScalarMetric<T, metric_kind_t> {
 
   /// Atomically reads the current value.
   virtual T GetValue() override {
-    boost::lock_guard<SpinLock> l(lock_);
+    std::lock_guard<SpinLock> l(lock_);
     return value_;
   }
 
   /// Atomically sets the value.
   void SetValue(const T& value) {
-    boost::lock_guard<SpinLock> l(lock_);
+    std::lock_guard<SpinLock> l(lock_);
     value_ = value;
   }
 
@@ -359,7 +359,7 @@ class MetricGroup {
   template <typename M>
   M* RegisterMetric(M* metric) {
     DCHECK(!metric->key_.empty());
-    boost::lock_guard<SpinLock> l(lock_);
+    std::lock_guard<SpinLock> l(lock_);
     DCHECK(metric_map_.find(metric->key_) == metric_map_.end()) << metric->key_;
     std::shared_ptr<M> metric_ptr(metric);
     metric_map_[metric->key_] = metric_ptr;
@@ -372,7 +372,7 @@ class MetricGroup {
   void RemoveMetric(const std::string& key, const std::string& metric_def_arg = "") {
     TMetricDef metric_def = MetricDefs::Get(key, metric_def_arg);
     DCHECK(!metric_def.key.empty());
-    boost::lock_guard<SpinLock> l(lock_);
+    std::lock_guard<SpinLock> l(lock_);
     DCHECK(metric_map_.find(metric_def.key) != metric_map_.end()) << metric_def.key;
     metric_map_.erase(metric_def.key);
     }
diff --git a/be/src/util/periodic-counter-updater.h b/be/src/util/periodic-counter-updater.h
index ed3676e..0f92070 100644
--- a/be/src/util/periodic-counter-updater.h
+++ b/be/src/util/periodic-counter-updater.h
@@ -17,9 +17,9 @@
 
 #pragma once
 
+#include <mutex>
 #include <boost/function.hpp>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 #include <boost/thread/thread.hpp>
 #include <boost/unordered_map.hpp>
 #include <boost/unordered_set.hpp>
diff --git a/be/src/util/promise-test.cc b/be/src/util/promise-test.cc
index 42ee4d7..16f1527 100644
--- a/be/src/util/promise-test.cc
+++ b/be/src/util/promise-test.cc
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
 
 #include "runtime/timestamp-value.h"
 #include "testutil/gtest-util.h"
diff --git a/be/src/util/promise.h b/be/src/util/promise.h
index f5a79cf..c80ffc8 100644
--- a/be/src/util/promise.h
+++ b/be/src/util/promise.h
@@ -19,7 +19,7 @@
 #define IMPALA_UTIL_PROMISE_H
 
 #include <algorithm>
-#include <boost/thread.hpp>
+#include <mutex>
 
 #include "util/condition-variable.h"
 #include "util/time.h"
@@ -56,7 +56,7 @@ class Promise {
   /// set before this call.
   /// It is invalid to call Set() twice if the PromiseMode is SINGLE_PRODUCER.
   T Set(const T& val) {
-    boost::unique_lock<boost::mutex> l(val_lock_);
+    std::unique_lock<std::mutex> l(val_lock_);
     if (val_is_set_) {
       DCHECK_ENUM_EQ(mode, PromiseMode::MULTIPLE_PRODUCER)
           << "Called Set(..) twice on the same Promise in SINGLE_PRODUCER mode";
@@ -82,7 +82,7 @@ class Promise {
   /// Blocks until a value is set, and then returns a reference to that value. Once Get()
   /// returns, the returned value will not change, since Set(..) may not be called twice.
   const T& Get() {
-    boost::unique_lock<boost::mutex> l(val_lock_);
+    std::unique_lock<std::mutex> l(val_lock_);
     while (!val_is_set_) {
       val_set_cond_.Wait(l);
     }
@@ -99,7 +99,7 @@ class Promise {
     DCHECK_GT(timeout_millis, 0);
     int64_t timeout_micros = timeout_millis * MICROS_PER_MILLI;
     DCHECK(timed_out != NULL);
-    boost::unique_lock<boost::mutex> l(val_lock_);
+    std::unique_lock<std::mutex> l(val_lock_);
     int64_t start;
     int64_t now;
     now = start = MonotonicMicros();
@@ -114,7 +114,7 @@ class Promise {
 
   /// Returns whether the value is set.
   bool IsSet() {
-    boost::lock_guard<boost::mutex> l(val_lock_);
+    std::lock_guard<std::mutex> l(val_lock_);
     return val_is_set_;
   }
 
@@ -123,7 +123,7 @@ class Promise {
   /// access to val_;
   ConditionVariable val_set_cond_;
   bool val_is_set_;
-  boost::mutex val_lock_;
+  std::mutex val_lock_;
 
   /// The actual value transferred from producer to consumer
   T val_;
diff --git a/be/src/util/runtime-profile-counters.h b/be/src/util/runtime-profile-counters.h
index 2c0b740..398ef20 100644
--- a/be/src/util/runtime-profile-counters.h
+++ b/be/src/util/runtime-profile-counters.h
@@ -577,7 +577,7 @@ class RuntimeProfile::EventSequence {
   /// (relative to the first time Start() was called) as the timestamp.
   void MarkEvent(std::string label) {
     Event event = make_pair(move(label), sw_.ElapsedTime() + offset_);
-    boost::lock_guard<SpinLock> event_lock(lock_);
+    std::lock_guard<SpinLock> event_lock(lock_);
     events_.emplace_back(move(event));
   }
 
@@ -593,7 +593,7 @@ class RuntimeProfile::EventSequence {
   /// timestamps. The supplied vector 'events' is cleared before this.
   void GetEvents(std::vector<Event>* events) {
     events->clear();
-    boost::lock_guard<SpinLock> event_lock(lock_);
+    std::lock_guard<SpinLock> event_lock(lock_);
     /// It's possible that MarkEvent() logs concurrent events out of sequence so we sort
     /// the events each time we are here.
     SortEvents();
@@ -607,7 +607,7 @@ class RuntimeProfile::EventSequence {
       const std::vector<int64_t>& timestamps, const std::vector<std::string>& labels) {
     DCHECK_EQ(timestamps.size(), labels.size());
     DCHECK(std::is_sorted(timestamps.begin(), timestamps.end()));
-    boost::lock_guard<SpinLock> event_lock(lock_);
+    std::lock_guard<SpinLock> event_lock(lock_);
     int64_t last_timestamp = events_.empty() ? 0 : events_.back().second;
     for (int64_t i = 0; i < timestamps.size(); ++i) {
       if (timestamps[i] <= last_timestamp) continue;
diff --git a/be/src/util/runtime-profile.cc b/be/src/util/runtime-profile.cc
index ae9aa46..1ffc922 100644
--- a/be/src/util/runtime-profile.cc
+++ b/be/src/util/runtime-profile.cc
@@ -20,11 +20,10 @@
 #include <algorithm>
 #include <iomanip>
 #include <iostream>
+#include <mutex>
 #include <utility>
 
 #include <boost/bind.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/thread.hpp>
 
 #include "common/object-pool.h"
 #include "gutil/strings/strip.h"
@@ -67,7 +66,7 @@ const string RuntimeProfile::INACTIVE_TIME_COUNTER_NAME = "InactiveTotalTime";
 constexpr ProfileEntryPrototype::Significance ProfileEntryPrototype::ALLSIGNIFICANCE[];
 
 void ProfileEntryPrototypeRegistry::AddPrototype(const ProfileEntryPrototype* prototype) {
-  boost::lock_guard<SpinLock> l(lock_);
+  lock_guard<SpinLock> l(lock_);
   DCHECK(prototypes_.find(prototype->name()) == prototypes_.end()) <<
       "Found duplicate prototype name: " << prototype->name();
   prototypes_.emplace(prototype->name(), prototype);
@@ -1700,7 +1699,7 @@ void RuntimeProfile::TimeSeriesCounter::ToJson(Document& document, Value* val) {
 }
 
 void RuntimeProfile::EventSequence::ToJson(Document& document, Value* value) {
-  boost::lock_guard<SpinLock> event_lock(lock_);
+  lock_guard<SpinLock> event_lock(lock_);
   SortEvents();
 
   Value event_sequence_json(kObjectType);
diff --git a/be/src/util/runtime-profile.h b/be/src/util/runtime-profile.h
index 80d24fb..9b3abf8 100644
--- a/be/src/util/runtime-profile.h
+++ b/be/src/util/runtime-profile.h
@@ -17,9 +17,9 @@
 
 #pragma once
 
-#include <boost/function.hpp>
-#include <boost/thread/lock_guard.hpp>
 #include <iosfwd>
+
+#include <boost/function.hpp>
 #include <rapidjson/document.h>
 #include "common/atomic.h"
 #include "common/status.h"
diff --git a/be/src/util/sharded-query-map-util.h b/be/src/util/sharded-query-map-util.h
index 1c66cfe..5b8ae14 100644
--- a/be/src/util/sharded-query-map-util.h
+++ b/be/src/util/sharded-query-map-util.h
@@ -17,7 +17,7 @@
 
 #pragma once
 
-#include <boost/thread/lock_guard.hpp>
+#include <mutex>
 #include <unordered_map>
 
 #include "gen-cpp/Types_types.h"
@@ -47,7 +47,7 @@ class ShardedQueryMap {
   // TODO: If necessary, refactor the lambda signature to allow returning Status objects.
   void DoFuncForAllEntries(const std::function<void(const T&)>& call) {
     for (int i = 0; i < NUM_QUERY_BUCKETS; ++i) {
-      boost::lock_guard<SpinLock> l(shards_[i].map_lock_);
+      std::lock_guard<SpinLock> l(shards_[i].map_lock_);
       for (const auto& map_value_ref: shards_[i].map_) {
         call(map_value_ref.second);
       }
diff --git a/be/src/util/simple-logger.cc b/be/src/util/simple-logger.cc
index 9b0592f..dff82ff 100644
--- a/be/src/util/simple-logger.cc
+++ b/be/src/util/simple-logger.cc
@@ -17,11 +17,12 @@
 
 #include "util/simple-logger.h"
 
+#include <mutex>
+
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 #include <boost/filesystem.hpp>
 #include <gutil/strings/substitute.h>
-#include <boost/thread/lock_guard.hpp>
 
 #include "common/names.h"
 #include "util/logging-support.h"
diff --git a/be/src/util/simple-logger.h b/be/src/util/simple-logger.h
index 6e101c5..42fb1c9 100644
--- a/be/src/util/simple-logger.h
+++ b/be/src/util/simple-logger.h
@@ -18,7 +18,7 @@
 #pragma once
 
 #include <fstream>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
 
 #include "common/status.h"
 
@@ -49,7 +49,7 @@ class SimpleLogger {
 
  private:
   /// Protects log_file_, num_log_file_entries_ and log_file_name_
-  boost::mutex log_file_lock_;
+  std::mutex log_file_lock_;
 
   /// Directory to log to
   std::string log_dir_;
diff --git a/be/src/util/stopwatch.h b/be/src/util/stopwatch.h
index 0c51a4f..96fed81 100644
--- a/be/src/util/stopwatch.h
+++ b/be/src/util/stopwatch.h
@@ -18,8 +18,8 @@
 #pragma once
 
 #include <cstdint>
+#include <mutex>
 
-#include <boost/thread/lock_guard.hpp>
 #include <util/os-info.h>
 #include <util/spinlock.h>
 #include <util/time.h>
@@ -201,7 +201,7 @@ class ConcurrentStopWatch {
   ConcurrentStopWatch() : busy_threads_(0), last_lap_start_(0) {}
 
   void Start() {
-    boost::lock_guard<SpinLock> l(thread_counter_lock_);
+    std::lock_guard<SpinLock> l(thread_counter_lock_);
     if (busy_threads_ == 0) {
       msw_.Start();
     }
@@ -209,7 +209,7 @@ class ConcurrentStopWatch {
   }
 
   void Stop() {
-    boost::lock_guard<SpinLock> l(thread_counter_lock_);
+    std::lock_guard<SpinLock> l(thread_counter_lock_);
     DCHECK_GT(busy_threads_, 0);
     --busy_threads_;
     if (busy_threads_ == 0) {
@@ -219,7 +219,7 @@ class ConcurrentStopWatch {
 
   /// Returns delta wall time since last time LapTime() is called.
   uint64_t LapTime() {
-    boost::lock_guard<SpinLock> l(thread_counter_lock_);
+    std::lock_guard<SpinLock> l(thread_counter_lock_);
     uint64_t now = msw_.ElapsedTime();
     uint64_t lap_duration = now - last_lap_start_;
     last_lap_start_ = now;
@@ -227,7 +227,7 @@ class ConcurrentStopWatch {
   }
 
   uint64_t TotalRunningTime() const {
-    boost::lock_guard<SpinLock> l(thread_counter_lock_);
+    std::lock_guard<SpinLock> l(thread_counter_lock_);
     return msw_.ElapsedTime();
   }
 
diff --git a/be/src/util/thread-pool-test.cc b/be/src/util/thread-pool-test.cc
index 4aa2d94..f20e3ed 100644
--- a/be/src/util/thread-pool-test.cc
+++ b/be/src/util/thread-pool-test.cc
@@ -16,8 +16,9 @@
 // under the License.
 
 #include <unistd.h>
-#include <boost/thread.hpp>
-#include <boost/thread/pthread/mutex.hpp>
+#include <mutex>
+
+#include <boost/thread/thread.hpp>
 #include <glog/logging.h>
 
 #include "common/logging.h"
diff --git a/be/src/util/thread-pool.h b/be/src/util/thread-pool.h
index dca55a3..6653ecc 100644
--- a/be/src/util/thread-pool.h
+++ b/be/src/util/thread-pool.h
@@ -17,12 +17,12 @@
 
 #pragma once
 
-#include "util/blocking-queue.h"
+#include <mutex>
 
 #include <boost/bind/mem_fn.hpp>
-#include <boost/thread/pthread/mutex.hpp>
 
 #include "util/aligned-new.h"
+#include "util/blocking-queue.h"
 #include "util/condition-variable.h"
 #include "util/thread.h"
 
@@ -124,7 +124,7 @@ class ThreadPool : public CacheLineAligned {
   /// terminate.
   void Shutdown() {
     {
-      boost::lock_guard<boost::mutex> l(lock_);
+      std::lock_guard<std::mutex> l(lock_);
       shutdown_ = true;
     }
     work_queue_.Shutdown();
@@ -145,7 +145,7 @@ class ThreadPool : public CacheLineAligned {
   /// Any work Offer()'ed during DrainAndShutdown may or may not be processed.
   void DrainAndShutdown() {
     {
-      boost::unique_lock<boost::mutex> l(lock_);
+      std::unique_lock<std::mutex> l(lock_);
       // If the ThreadPool is not initialized, then the queue must be empty.
       DCHECK(initialized_ || work_queue_.Size() == 0);
       while (work_queue_.Size() != 0) {
@@ -169,7 +169,7 @@ class ThreadPool : public CacheLineAligned {
         /// Take lock to ensure that DrainAndShutdown() cannot be between checking
         /// GetSize() and wait()'ing when the condition variable is notified.
         /// (It will hang if we notify right before calling wait().)
-        boost::unique_lock<boost::mutex> l(lock_);
+        std::unique_lock<std::mutex> l(lock_);
         empty_cv_.NotifyAll();
       }
     }
@@ -177,7 +177,7 @@ class ThreadPool : public CacheLineAligned {
 
   /// Returns value of shutdown_ under a lock, forcing visibility to threads in the pool.
   bool IsShutdown() {
-    boost::lock_guard<boost::mutex> l(lock_);
+    std::lock_guard<std::mutex> l(lock_);
     return shutdown_;
   }
 
@@ -205,7 +205,7 @@ class ThreadPool : public CacheLineAligned {
   ThreadGroup threads_;
 
   /// Guards shutdown_ and empty_cv_
-  boost::mutex lock_;
+  std::mutex lock_;
 
   /// Set to true when Init() has finished spawning the threads.
   bool initialized_ = false;
diff --git a/be/src/util/thread.h b/be/src/util/thread.h
index a76932c..3d10424 100644
--- a/be/src/util/thread.h
+++ b/be/src/util/thread.h
@@ -24,7 +24,7 @@
 #include <boost/bind.hpp>
 #include <boost/function.hpp>
 #include <boost/scoped_ptr.hpp>
-#include <boost/thread.hpp>
+#include <boost/thread/thread_only.hpp>
 
 #include "common/status.h"
 #include "util/promise.h"
diff --git a/be/src/util/webserver.cc b/be/src/util/webserver.cc
index c3dc7b7..9a0ef70 100644
--- a/be/src/util/webserver.cc
+++ b/be/src/util/webserver.cc
@@ -27,7 +27,7 @@
 #include <boost/filesystem.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/mem_fn.hpp>
-#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
 #include <rapidjson/document.h>
 #include <rapidjson/prettywriter.h>
 #include <rapidjson/stringbuffer.h>