# How to Configure absl::Mutex Scheduling Modes: kNormal vs kFatals

> Learn how to configure absl::Mutex scheduling modes kNormal vs kFatals for optimal performance and error detection. Pass absl::MutexOptions to the constructor.

- Repository: [Abseil/abseil-cpp](https://github.com/abseil/abseil-cpp)
- Tags: how-to-guide
- Published: 2026-07-11

---

**You configure an `absl::Mutex` scheduling mode by passing an `absl::Mutex::Options` object with `set_scheduling_mode()` to the constructor, choosing between `kNormal` for balanced performance or `kFatals` for strict error detection.**

The `absl::Mutex` class in the [Abseil C++ library](https://github.com/abseil/abseil-cpp) supports configurable scheduling policies that control how contending threads are managed. These policies are defined by the `SchedulingMode` enum in [`absl/base/internal/scheduling_mode.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/base/internal/scheduling_mode.h) and set through the `Mutex::Options` struct. Selecting the appropriate mode allows you to optimize for production latency or enable aggressive error checking during debugging.

## Understanding Scheduling Modes

The scheduling mode determines the runtime behavior when threads compete for lock acquisition. The implementation varies between balanced spinning/yielding and strict fatal error detection.

### kNormal Mode (Default)

`absl::base_internal::SchedulingMode::kNormal` is the default policy when no options are specified. In this mode, the mutex uses a hybrid approach that briefly spins before yielding or blocking threads, balancing low latency against CPU consumption. This mode is suitable for production environments where you want optimal performance without sacrificing fairness.

### kFatals Mode (Strict Error Detection)

`absl::base_internal::SchedulingMode::kFatals` enables a strict policy that disables background thread yielding and forces immediate termination on synchronization anomalies. Use this mode in test suites or debugging scenarios where you need the program to abort instantly upon deadlocks, double-unlocks, or other fatal synchronization errors.

## Configuring the Scheduling Mode

You specify the scheduling mode at construction time by creating an `absl::Mutex::Options` object and calling `set_scheduling_mode()`. Pass this options object to the `absl::Mutex` constructor.

```cpp
#include "absl/base/internal/scheduling_mode.h"
#include "absl/synchronization/mutex.h"

int main() {
  // Default kNormal mode (implicit)
  absl::Mutex normal_mutex;

  // Explicit kNormal configuration
  absl::Mutex::Options normal_opts;
  normal_opts.set_scheduling_mode(absl::base_internal::SchedulingMode::kNormal);
  absl::Mutex explicit_normal(normal_opts);

  // kFatals configuration for strict checking
  absl::Mutex::Options fatals_opts;
  fatals_opts.set_scheduling_mode(absl::base_internal::SchedulingMode::kFatals);
  absl::Mutex fatal_mutex(fatals_opts);

  // Usage remains identical regardless of mode
  {
    absl::MutexLock lock(&fatal_mutex);
    // Critical section: anomalies here trigger immediate abort
  }
}

```

## Key Source Files

The scheduling mode implementation spans three critical files in the Abseil repository:

- **[`absl/base/internal/scheduling_mode.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/base/internal/scheduling_mode.h)** – Defines the `SchedulingMode` enum including `kNormal` and `kFatals`.
- **[`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h)** – Declares `absl::Mutex`, the `Options` struct, and the `set_scheduling_mode` method.
- **[`absl/base/internal/low_level_scheduling.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/base/internal/low_level_scheduling.h)** – Implements the low-level logic that interprets the scheduling mode flag during lock contention.

## When to Use Each Mode

Choose your scheduling mode based on the environment and debugging requirements:

- **Production code** – Use `kNormal` to allow the runtime to optimize thread waking and blocking decisions for throughput and latency.
- **Testing and debugging** – Use `kFatals` to surface synchronization bugs immediately through process termination, making it easier to identify deadlock or logic errors during development.

## Summary

- Configure `absl::Mutex` scheduling modes via `absl::Mutex::Options` and `set_scheduling_mode()` at construction time.
- **`kNormal`** provides balanced spinning and yielding for production performance.
- **`kFatals`** forces immediate abort on synchronization errors for debugging.
- The options are defined in [`absl/base/internal/scheduling_mode.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/base/internal/scheduling_mode.h) and consumed by the mutex implementation in [`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h).

## Frequently Asked Questions

### How do I set the scheduling mode on an existing absl::Mutex?

You cannot change the scheduling mode after construction. The mode is fixed when the mutex is initialized, so you must configure it via `absl::Mutex::Options` in the constructor.

### What is the difference between kNormal and kFatals scheduling modes?

`kNormal` allows the runtime to spin, yield, and block threads using adaptive algorithms optimized for performance. `kFatals` disables these optimizations and triggers immediate program termination if the mutex detects anomalies like deadlocks or double-unlocks.

### Can I use kFatals mode in production?

While technically possible, `kFatals` is not recommended for production deployments because it sacrifices performance optimizations and can crash the process on recoverable contention scenarios. Reserve this mode for unit tests and debug builds.

### Where are the scheduling mode definitions located in the Abseil source code?

The enum definitions reside in [`absl/base/internal/scheduling_mode.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/base/internal/scheduling_mode.h), the API for setting them is in [`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h), and the underlying behavior is implemented in [`absl/base/internal/low_level_scheduling.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/base/internal/low_level_scheduling.h).