Bird
Raised Fist0
Swiftprogramming~10 mins

Sendable protocol for thread safety in Swift - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Sendable protocol for thread safety
Define a type
↓
Conform to Sendable
↓
Use in concurrent code
↓
Compiler checks thread safety
↓
Safe data sharing
↓
Avoid data races
The Sendable protocol marks types as safe to share across threads. The compiler checks this to prevent data races.
Execution Sample
Swift
struct Counter: Sendable {
    var value: Int
}

func update(counter: inout Counter) {
    counter.value += 1
}
Defines a thread-safe Counter struct conforming to Sendable and updates it asynchronously.
Execution Table
StepActionEvaluationResult
1Define struct Counter with Int valueCounter is SendableCounter marked safe for concurrency
2Call update(counter:) asynchronouslycounter.value = 0 initiallyPrepare to increment
3Increment counter.value by 1counter.value was 0counter.value becomes 1
4Function completesNo data race detectedSafe update confirmed
5ExitAll operations thread-safeExecution ends
💡 Function completes with thread-safe update, no data races
Variable Tracker
VariableStartAfter 1After 2Final
counter.value0011
Key Moments - 3 Insights
Why must Counter conform to Sendable?
Because the compiler uses Sendable to check if Counter can be safely shared across threads, as shown in step 1 of the execution_table.
What happens if Counter has a non-Sendable property?
The compiler will give an error during the check in step 1, preventing unsafe concurrent use.
Why is incrementing counter.value safe here?
Because the function runs asynchronously but the type is Sendable, ensuring no data races as seen in steps 3 and 4.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is counter.value after step 3?
A1
B0
CUndefined
D2
💡 Hint
Check the 'Result' column at step 3 in the execution_table.
At which step does the compiler confirm thread safety?
AStep 2
BStep 3
CStep 1
DStep 4
💡 Hint
Look at the 'Evaluation' column in step 1 where Sendable conformance is checked.
If Counter had a non-Sendable property, what would change in the execution_table?
AStep 3 would increment twice
BStep 1 would show a compiler error
CStep 4 would show data race detected
DNo change
💡 Hint
Refer to key_moments about compiler checks at step 1.
Concept Snapshot
Sendable protocol marks types safe for concurrency.
Conform your types to Sendable to share across threads.
Compiler checks Sendable conformance to prevent data races.
Use Sendable types in async or concurrent code safely.
Non-Sendable properties cause compile errors.
Always prefer immutable or thread-safe data for concurrency.
Full Transcript
The Sendable protocol in Swift is used to mark types that can be safely shared across threads. When you define a type like a struct, you can conform it to Sendable. The compiler then checks if all properties are also Sendable. This ensures no data races happen when the type is used in concurrent or asynchronous code. For example, a Counter struct with an Int value can conform to Sendable. When you update this counter asynchronously, the compiler confirms thread safety. If the type had a non-Sendable property, the compiler would give an error. This helps keep your code safe and free from hard-to-find bugs caused by concurrent access.

Practice

(1/5)
1. What does the Sendable protocol in Swift ensure?
easy
A. That a function runs asynchronously.
B. That a class can only be used on the main thread.
C. That a variable is immutable.
D. That data can be safely shared between threads without causing race conditions.

Solution

  1. Step 1: Understand the purpose of Sendable

    The Sendable protocol marks types that can be safely passed between threads without causing data races.
  2. Step 2: Compare options with the definition

    Only That data can be safely shared between threads without causing race conditions. correctly describes this safety guarantee. Other options describe unrelated concepts.
  3. Final Answer:

    That data can be safely shared between threads without causing race conditions. -> Option D
  4. Quick Check:

    Sendable = safe cross-thread data sharing [OK]
Hint: Sendable means safe to share data across threads [OK]
Common Mistakes:
  • Confusing Sendable with immutability
  • Thinking Sendable restricts to main thread only
  • Assuming Sendable makes functions async
2. Which of the following is the correct way to declare a struct as Sendable in Swift?
easy
A. struct Data { var value: Int } implements Sendable
B. struct Data: Sendable { var value: Int }
C. struct Data Sendable { var value: Int }
D. struct Data { var value: Int } : Sendable

Solution

  1. Step 1: Recall Swift protocol conformance syntax

    In Swift, a type conforms to a protocol by listing it after a colon following the type name.
  2. Step 2: Match syntax to options

    struct Data: Sendable { var value: Int } uses correct syntax: struct Data: Sendable { ... }. Others are invalid Swift syntax.
  3. Final Answer:

    struct Data: Sendable { var value: Int } -> Option B
  4. Quick Check:

    Protocol conformance uses colon after type name [OK]
Hint: Use colon after struct name to conform to Sendable [OK]
Common Mistakes:
  • Placing protocol after braces
  • Using 'implements' keyword (not Swift)
  • Omitting colon between type and protocol
3. What will happen when you try to compile this Swift code?
struct Counter: Sendable {
  var count: Int
}

let counter = Counter(count: 5)
Task {
  print(counter.count)
}
medium
A. It compiles and prints 5.
B. It causes a compile-time error because Counter is not Sendable.
C. It causes a runtime error due to thread safety violation.
D. It compiles but prints 0.

Solution

  1. Step 1: Check if Counter conforms to Sendable

    The struct explicitly conforms to Sendable and contains only an Int, which is Sendable.
  2. Step 2: Understand Task usage

    The Task runs asynchronously but can safely access counter because it is Sendable.
  3. Final Answer:

    It compiles and prints 5. -> Option A
  4. Quick Check:

    Sendable struct with Int prints value safely [OK]
Hint: Sendable structs with simple types compile and run safely [OK]
Common Mistakes:
  • Assuming compile error without checking conformance
  • Confusing runtime errors with compile errors
  • Thinking default structs are not Sendable
4. Identify the error in this Swift code using Sendable:
class DataHolder: Sendable {
  var data: [Int]
  init(data: [Int]) {
    self.data = data
  }
}
medium
A. Missing explicit Sendable conformance on Array.
B. Class cannot conform to Sendable at all.
C. Array<Int> is not Sendable by default, causing a compile error.
D. No error; code compiles fine.

Solution

  1. Step 1: Check Sendable conformance for class with mutable property

    Classes with mutable stored properties like arrays are not automatically Sendable.
  2. Step 2: Understand why Array<Int> is not Sendable by default

    Array is a reference type and mutable, so compiler disallows automatic Sendable conformance without extra guarantees.
  3. Final Answer:

    Array<Int> is not Sendable by default, causing a compile error. -> Option C
  4. Quick Check:

    Mutable reference types block Sendable conformance [OK]
Hint: Mutable class properties like arrays block Sendable by default [OK]
Common Mistakes:
  • Thinking classes cannot conform to Sendable at all
  • Assuming arrays are always Sendable
  • Ignoring mutability in Sendable checks
5. You want to make this struct safely shareable across threads. What is the best way to fix it?
struct UserData: Sendable {
  var name: String
  var preferences: [String: String]
}
hard
A. Make preferences an immutable dictionary and ensure keys and values are Sendable.
B. Remove Sendable conformance because dictionaries are never Sendable.
C. Change preferences to a class type and mark it as Sendable.
D. Add @Sendable attribute to the struct.

Solution

  1. Step 1: Understand Sendable requirements for dictionary properties

    Dictionaries are Sendable only if their keys and values are Sendable and the dictionary is used immutably.
  2. Step 2: Apply immutability and ensure key/value types conform

    Making preferences immutable (let) and using Sendable key/value types (String) satisfies Sendable.
  3. Final Answer:

    Make preferences an immutable dictionary and ensure keys and values are Sendable. -> Option A
  4. Quick Check:

    Immutable dictionary with Sendable types = Sendable struct [OK]
Hint: Use immutable dictionary with Sendable keys/values for Sendable struct [OK]
Common Mistakes:
  • Thinking dictionaries are never Sendable
  • Confusing @Sendable attribute with Sendable protocol
  • Using mutable properties in Sendable structs
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard