Bird
Raised Fist0
Swiftprogramming~20 mins

Why actors prevent data races in Swift - Challenge Your Understanding

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Actor Mastery Badge
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Understanding actor isolation in Swift
What will be the output of this Swift code using an actor to protect shared data?
Swift
actor Counter {
    var value = 0
    func increment() async {
        value += 1
    }
    func getValue() async -> Int {
        return value
    }
}

let counter = Counter()
Task {
    await counter.increment()
    let val = await counter.getValue()
    print(val)
}
ARuntime error due to data race
B0
CCompilation error due to missing await
D1
Attempts:
2 left
💡 Hint
Remember that actors serialize access to their mutable state.
🧠 Conceptual
intermediate
1:30remaining
Why do actors prevent data races?
Which statement best explains why Swift actors prevent data races?
AActors serialize access to their mutable state, ensuring only one task can modify it at a time.
BActors allow multiple threads to write to the same variable simultaneously.
CActors disable concurrency to avoid any parallel execution.
DActors copy all data before modifying it, so no shared state exists.
Attempts:
2 left
💡 Hint
Think about how actors control access to their internal data.
🔧 Debug
advanced
2:30remaining
Identify the data race in this Swift code
What error or problem will occur when running this code without using an actor?
Swift
class Counter {
    var value = 0
    func increment() {
        value += 1
    }
}

let counter = Counter()
DispatchQueue.concurrentPerform(iterations: 1000) { _ in
    counter.increment()
}
print(counter.value)
AThe printed value will always be 1000
BThe printed value may be less than 1000 due to a data race
CCompilation error because DispatchQueue.concurrentPerform is not allowed
DRuntime crash due to actor isolation violation
Attempts:
2 left
💡 Hint
Consider what happens when multiple threads modify the same variable without synchronization.
📝 Syntax
advanced
2:00remaining
Which code snippet correctly uses an actor to prevent data races?
Choose the code that correctly defines and uses an actor to safely increment a counter.
A
actor Counter {
    var value = 0
    func increment() async {
        value += 1
    }
}

let counter = Counter()
await counter.increment()
B
actor Counter {
    var value = 0
    func increment() {
        value += 1
    }
}

let counter = Counter()
counter.increment()
C
class Counter {
    var value = 0
    func increment() async {
        value += 1
    }
}

let counter = Counter()
await counter.increment()
D
actor Counter {
    var value = 0
    func increment() async {
        value += 1
    }
}

let counter = Counter()
counter.increment()
Attempts:
2 left
💡 Hint
Remember that actor methods that modify state are asynchronous and must be awaited.
🚀 Application
expert
3:00remaining
Predict the final value with concurrent actor calls
Given this Swift code, what is the final printed value of the counter after all tasks complete?
Swift
actor Counter {
    var value = 0
    func increment() async {
        let current = value
        try? await Task.sleep(nanoseconds: 1_000_000) // simulate delay
        value = current + 1
    }
    func getValue() async -> Int {
        return value
    }
}

let counter = Counter()

Task {
    await withTaskGroup(of: Void.self) { group in
        for _ in 1...10 {
            group.addTask {
                await counter.increment()
            }
        }
    }
    let finalValue = await counter.getValue()
    print(finalValue)
}
A0
B1
C10
DRuntime error due to data race
Attempts:
2 left
💡 Hint
Actors serialize access even if tasks run concurrently.

Practice

(1/5)
1. Why do Swift actors help prevent data races?
easy
A. They duplicate data for each task automatically.
B. They allow only one task to access their data at a time.
C. They run all tasks in parallel without waiting.
D. They disable concurrency features in Swift.

Solution

  1. Step 1: Understand what a data race is

    A data race happens when multiple tasks try to change the same data at the same time.
  2. Step 2: How actors manage access

    Actors allow only one task to access or change their data at once, preventing simultaneous changes.
  3. Final Answer:

    They allow only one task to access their data at a time. -> Option B
  4. Quick Check:

    Actors serialize access = prevent data races [OK]
Hint: Actors serialize access to data, so no simultaneous changes happen [OK]
Common Mistakes:
  • Thinking actors duplicate data for each task
  • Believing actors run tasks in parallel without control
  • Assuming actors disable concurrency features
2. Which is the correct way to call an actor's method in Swift?
easy
A. actorInstance.method()
B. actorInstance.method.await()
C. await actorInstance.method()
D. async actorInstance.method()

Solution

  1. Step 1: Recall actor method call syntax

    Actor methods are asynchronous and require the await keyword to call.
  2. Step 2: Identify correct usage

    The correct syntax is to write await actorInstance.method() to wait for the method to complete.
  3. Final Answer:

    await actorInstance.method() -> Option C
  4. Quick Check:

    Use await before actor calls [OK]
Hint: Always use await before calling actor methods [OK]
Common Mistakes:
  • Calling actor methods without await
  • Using async keyword incorrectly in call
  • Placing await after method call
3. What will be the output of this Swift code?
actor Counter {
    var value = 0
    func increment() {
        value += 1
    }
}

let counter = Counter()
Task {
    await counter.increment()
    print(await counter.value)
}
medium
A. 0
B. Runtime crash
C. 1
D. Compilation error

Solution

  1. Step 1: Understand actor property access

    Accessing actor properties from outside requires await because it is asynchronous.
  2. Step 2: Trace the code execution

    The increment() method increases value by 1, but since increment() is not marked as async, calling it with await causes a compilation error.
  3. Final Answer:

    Compilation error -> Option D
  4. Quick Check:

    increment() must be async to be awaited [OK]
Hint: increment() must be async to be awaited [OK]
Common Mistakes:
  • Forgetting await when accessing actor property
  • Expecting 0 because of missing synchronization
  • Assuming increment is synchronous
4. Identify the error in this Swift actor code:
actor BankAccount {
    var balance = 0
    func deposit(amount: Int) {
        balance += amount
    }
}

let account = BankAccount()
Task {
    account.deposit(amount: 100)
    print(await account.balance)
}
medium
A. Missing await before deposit call
B. balance should be a constant
C. deposit method cannot modify balance
D. print statement should not use await

Solution

  1. Step 1: Check actor method call rules

    Calling an actor's method from outside must use await because it's asynchronous.
  2. Step 2: Identify missing await

    The code calls account.deposit(amount: 100) without await, causing a compile error.
  3. Final Answer:

    Missing await before deposit call -> Option A
  4. Quick Check:

    Actor method calls require await [OK]
Hint: Always put await before actor method calls outside actor [OK]
Common Mistakes:
  • Ignoring await on actor method calls
  • Thinking balance must be constant
  • Assuming print can't await actor properties
5. Given this actor code, why does using an actor prevent a data race when multiple tasks call increment()?
actor SafeCounter {
    var count = 0
    func increment() {
        count += 1
    }
}
hard
A. Because actor methods run one at a time, queuing calls safely.
B. Because the count variable is copied for each task.
C. Because Swift disables concurrency inside actors.
D. Because increment() is automatically atomic without queuing.

Solution

  1. Step 1: Understand actor method execution

    Actor methods run serially, meaning one finishes before the next starts.
  2. Step 2: How this prevents data races

    Since calls to increment() are queued and run one by one, simultaneous changes to count cannot happen.
  3. Final Answer:

    Because actor methods run one at a time, queuing calls safely. -> Option A
  4. Quick Check:

    Actors serialize method calls = no data races [OK]
Hint: Actors queue method calls, so only one runs at a time [OK]
Common Mistakes:
  • Thinking variables are copied per task
  • Believing concurrency is disabled inside actors
  • Assuming increment is atomic without queuing
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