<!--
{
  "availability" : [
    "iOS: 16.0.0 -",
    "iPadOS: 16.0.0 -",
    "macCatalyst: -",
    "macOS: 13.0.0 -",
    "tvOS: 16.0.0 -",
    "visionOS: -",
    "watchOS: 9.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "os",
  "identifier" : "/documentation/os/OSAllocatedUnfairLock",
  "metadataVersion" : "0.1.0",
  "role" : "Structure",
  "symbol" : {
    "kind" : "Structure",
    "modules" : [
      "os"
    ],
    "preciseIdentifier" : "s:2os21OSAllocatedUnfairLockV"
  },
  "title" : "OSAllocatedUnfairLock"
}
-->

# OSAllocatedUnfairLock

A structure that creates an unfair lock.

```
@frozen struct OSAllocatedUnfairLock<State>
```

## Overview

Unfair locks are low-level locks that block efficiently on contention. They’re useful for protecting code that loads stored resources. However, it’s unsafe to use [`os_unfair_lock`](/documentation/os/os_unfair_lock) from Swift because it’s a value type and, therefore, doesn’t have a stable memory address. That means when you call [`os_unfair_lock_lock`](/documentation/os/os_unfair_lock_lock) or [`os_unfair_lock_unlock`](/documentation/os/os_unfair_lock_unlock) and pass a lock object using the `&` operator, the system may lock or unlock the wrong object.

Instead, use [`OSAllocatedUnfairLock`](/documentation/os/OSAllocatedUnfairLock), which avoids that pitfall because it doesn’t function as a value type, despite being a structure. All copied instances of an [`OSAllocatedUnfairLock`](/documentation/os/OSAllocatedUnfairLock) control the same underlying lock allocation.

> Important:
> If you’ve existing Swift code that uses ``doc://com.apple.os/documentation/os/os_unfair_lock``, change it to use ``doc://com.apple.os/documentation/os/OSAllocatedUnfairLock`` to ensure correct locking behavior.

To create a lock that protects operation state, create an enumeration that contains the possible states, then create a lock object, passing the initial state. Here’s an example of what that looks like for an asset load operation:

```swift
enum MyState {
    case idle
    case loading
    case complete(MyAsset)
    case error(Error)
}
let protectedState = OSAllocatedUnfairLock(initialState: MyState.idle)
```

Storing the state inside the lock helps track what the lock is protecting, and provides a way to safely access the state. To begin using the lock, call `withLock(_:)` or `withLockIfAvailable(_:)`, passing a closure that contains the code for the lock to protect, like in the following example:

```swift
func myLoadMethod() {
    protectedState.withLock { state in
        state = .loading
    }
    var (resource, error) = loadMyResources()
    if resource != nil {
        protectedState.withLock { state in
            state = .complete(resource)
        }
    } else {
        protectedState.withLock { state in
            state = .error(error!)
        }
    }
}
```

To protect an operation with an externally defined state or no state, create a lock object without specifying an initial state. Nonscoped locking is more flexible, but offers no assistance in tracking the state of the operation the lock protects. To use a nonscoped lock, use `withLock(_:)` or `withLockIfAvailable(_:)`.

```swift
let myLock = OSAllocatedUnfairLock()
myLock.withLock {
    // Code that needs protection.
}
```

You can also use [`OSAllocatedUnfairLock`](/documentation/os/OSAllocatedUnfairLock) with the more traditional lock/unlock approach by calling [`lock()`](/documentation/os/OSAllocatedUnfairLock/lock()) before executing code that needs protection, and [`unlock()`](/documentation/os/OSAllocatedUnfairLock/unlock()) upon completion, like this:

```swift
myLock.lock()
// Code that needs protection.
myLock.unlock()
```

When using this approach, you must call [`unlock()`](/documentation/os/OSAllocatedUnfairLock/unlock()) from the same thread you use to call [`lock()`](/documentation/os/OSAllocatedUnfairLock/lock()). Because of this, it’s unsafe to use this approach across an `await` suspension point. When using a lock with asynchronous code, lock using a closure or, even better, consider using an <doc://com.apple.documentation/documentation/Swift/Actor>.

> Warning:
> ``doc://com.apple.os/documentation/os/OSAllocatedUnfairLock`` isn’t a recursive lock. Attempting to lock an object more than once from the same thread without unlocking in between triggers a runtime exception.

## Topics

### Creating a lock object

[`init()`](/documentation/os/OSAllocatedUnfairLock/init())

Creates a lock object that doesn’t protect state data.

[`init(initialState:)`](/documentation/os/OSAllocatedUnfairLock/init(initialState:))

Creates a lock object that maintains and protects state data.

### Using locks

[`lock()`](/documentation/os/OSAllocatedUnfairLock/lock())

Acquires a lock.

[`lockIfAvailable()`](/documentation/os/OSAllocatedUnfairLock/lockIfAvailable())

Attempts to acquire a lock.

[`unlock()`](/documentation/os/OSAllocatedUnfairLock/unlock())

Ends the lock.

### Determining lock ownership

[`OSAllocatedUnfairLock.Ownership`](/documentation/os/OSAllocatedUnfairLock/Ownership)

An enumeration that represents the ownership status of an unfair lock.

[`precondition(_:)`](/documentation/os/OSAllocatedUnfairLock/precondition(_:))

Asserts if the lock object fails to meet specified ownership requirements.



---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)