diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 09d9c5163..b4718fbbe 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -16,7 +16,8 @@
 
 namespace Core {
 
-CpuManager::CpuManager(System& system_) : system{system_} {}
+CpuManager::CpuManager(System& system_)
+    : pause_barrier{std::make_unique<Common::Barrier>(1)}, system{system_} {}
 CpuManager::~CpuManager() = default;
 
 void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
@@ -30,8 +31,10 @@ void CpuManager::Initialize() {
         for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
             core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
         }
+        pause_barrier = std::make_unique<Common::Barrier>(Core::Hardware::NUM_CPU_CORES + 1);
     } else {
         core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0);
+        pause_barrier = std::make_unique<Common::Barrier>(2);
     }
 }
 
@@ -138,51 +141,14 @@ void CpuManager::MultiCoreRunSuspendThread() {
         auto core = kernel.CurrentPhysicalCoreIndex();
         auto& scheduler = *kernel.CurrentScheduler();
         Kernel::KThread* current_thread = scheduler.GetCurrentThread();
+        current_thread->DisableDispatch();
+
         Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
-        ASSERT(scheduler.ContextSwitchPending());
         ASSERT(core == kernel.CurrentPhysicalCoreIndex());
         scheduler.RescheduleCurrentCore();
     }
 }
 
-void CpuManager::MultiCorePause(bool paused) {
-    if (!paused) {
-        bool all_not_barrier = false;
-        while (!all_not_barrier) {
-            all_not_barrier = true;
-            for (const auto& data : core_data) {
-                all_not_barrier &= !data.is_running.load() && data.initialized.load();
-            }
-        }
-        for (auto& data : core_data) {
-            data.enter_barrier->Set();
-        }
-        if (paused_state.load()) {
-            bool all_barrier = false;
-            while (!all_barrier) {
-                all_barrier = true;
-                for (const auto& data : core_data) {
-                    all_barrier &= data.is_paused.load() && data.initialized.load();
-                }
-            }
-            for (auto& data : core_data) {
-                data.exit_barrier->Set();
-            }
-        }
-    } else {
-        /// Wait until all cores are paused.
-        bool all_barrier = false;
-        while (!all_barrier) {
-            all_barrier = true;
-            for (const auto& data : core_data) {
-                all_barrier &= data.is_paused.load() && data.initialized.load();
-            }
-        }
-        /// Don't release the barrier
-    }
-    paused_state = paused;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 ///                             SingleCore                                   ///
 ///////////////////////////////////////////////////////////////////////////////
@@ -235,8 +201,9 @@ void CpuManager::SingleCoreRunSuspendThread() {
         auto core = kernel.GetCurrentHostThreadID();
         auto& scheduler = *kernel.CurrentScheduler();
         Kernel::KThread* current_thread = scheduler.GetCurrentThread();
+        current_thread->DisableDispatch();
+
         Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[0].host_context);
-        ASSERT(scheduler.ContextSwitchPending());
         ASSERT(core == kernel.GetCurrentHostThreadID());
         scheduler.RescheduleCurrentCore();
     }
@@ -274,37 +241,21 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
     }
 }
 
-void CpuManager::SingleCorePause(bool paused) {
-    if (!paused) {
-        bool all_not_barrier = false;
-        while (!all_not_barrier) {
-            all_not_barrier = !core_data[0].is_running.load() && core_data[0].initialized.load();
-        }
-        core_data[0].enter_barrier->Set();
-        if (paused_state.load()) {
-            bool all_barrier = false;
-            while (!all_barrier) {
-                all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load();
-            }
-            core_data[0].exit_barrier->Set();
-        }
-    } else {
-        /// Wait until all cores are paused.
-        bool all_barrier = false;
-        while (!all_barrier) {
-            all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load();
-        }
-        /// Don't release the barrier
-    }
-    paused_state = paused;
-}
-
 void CpuManager::Pause(bool paused) {
-    if (is_multicore) {
-        MultiCorePause(paused);
-    } else {
-        SingleCorePause(paused);
+    std::scoped_lock lk{pause_lock};
+
+    if (pause_state == paused) {
+        return;
     }
+
+    // Set the new state
+    pause_state.store(paused);
+
+    // Wake up any waiting threads
+    pause_state.notify_all();
+
+    // Wait for all threads to successfully change state before returning
+    pause_barrier->Sync();
 }
 
 void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
@@ -320,27 +271,29 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
     Common::SetCurrentThreadName(name.c_str());
     Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
     auto& data = core_data[core];
-    data.enter_barrier = std::make_unique<Common::Event>();
-    data.exit_barrier = std::make_unique<Common::Event>();
     data.host_context = Common::Fiber::ThreadToFiber();
-    data.is_running = false;
-    data.initialized = true;
     const bool sc_sync = !is_async_gpu && !is_multicore;
     bool sc_sync_first_use = sc_sync;
 
     // Cleanup
     SCOPE_EXIT({
         data.host_context->Exit();
-        data.enter_barrier.reset();
-        data.exit_barrier.reset();
-        data.initialized = false;
         MicroProfileOnThreadExit();
     });
 
     /// Running
     while (running_mode) {
-        data.is_running = false;
-        data.enter_barrier->Wait();
+        if (pause_state.load(std::memory_order_relaxed)) {
+            // Wait for caller to acknowledge pausing
+            pause_barrier->Sync();
+
+            // Wait until unpaused
+            pause_state.wait(true, std::memory_order_relaxed);
+
+            // Wait for caller to acknowledge unpausing
+            pause_barrier->Sync();
+        }
+
         if (sc_sync_first_use) {
             system.GPU().ObtainContext();
             sc_sync_first_use = false;
@@ -352,12 +305,7 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
         }
 
         auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
-        data.is_running = true;
         Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
-        data.is_running = false;
-        data.is_paused = true;
-        data.exit_barrier->Wait();
-        data.is_paused = false;
     }
 }
 
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h
index aee352245..ddd9691ca 100644
--- a/src/core/cpu_manager.h
+++ b/src/core/cpu_manager.h
@@ -69,13 +69,11 @@ private:
     void MultiCoreRunGuestLoop();
     void MultiCoreRunIdleThread();
     void MultiCoreRunSuspendThread();
-    void MultiCorePause(bool paused);
 
     void SingleCoreRunGuestThread();
     void SingleCoreRunGuestLoop();
     void SingleCoreRunIdleThread();
     void SingleCoreRunSuspendThread();
-    void SingleCorePause(bool paused);
 
     static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
 
@@ -83,16 +81,13 @@ private:
 
     struct CoreData {
         std::shared_ptr<Common::Fiber> host_context;
-        std::unique_ptr<Common::Event> enter_barrier;
-        std::unique_ptr<Common::Event> exit_barrier;
-        std::atomic<bool> is_running;
-        std::atomic<bool> is_paused;
-        std::atomic<bool> initialized;
         std::jthread host_thread;
     };
 
     std::atomic<bool> running_mode{};
-    std::atomic<bool> paused_state{};
+    std::atomic<bool> pause_state{};
+    std::unique_ptr<Common::Barrier> pause_barrier{};
+    std::mutex pause_lock{};
 
     std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{};
 
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 92f6d8c49..7eb961912 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -252,6 +252,7 @@ struct KernelCore::Impl {
                                                          core_id)
                        .IsSuccess());
             suspend_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id));
+            suspend_threads[core_id]->DisableDispatch();
         }
     }
 
@@ -1073,9 +1074,6 @@ void KernelCore::Suspend(bool in_suspention) {
             impl->suspend_threads[core_id]->SetState(state);
             impl->suspend_threads[core_id]->SetWaitReasonForDebugging(
                 ThreadWaitReasonForDebugging::Suspended);
-            if (!should_suspend) {
-                impl->suspend_threads[core_id]->DisableDispatch();
-            }
         }
     }
 }