Challenge - 5 Problems
Concurrency Mastery: Actors vs Locks
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate2:00remaining
Output of concurrent access with actor
What will be the output of this Swift code using an actor to protect shared state?
Swift
actor Counter {
var value = 0
func increment() {
value += 1
}
func getValue() -> Int {
return value
}
}
let counter = Counter()
Task {
await counter.increment()
}
Task {
await counter.increment()
}
Task {
let val = await counter.getValue()
print(val)
}
// Wait a moment to let tasks finish
Thread.sleep(forTimeInterval: 0.1)Attempts:
2 left
💡 Hint
Actors serialize access to their internal state, so increments are safe.
✗ Incorrect
The actor ensures that increments happen one at a time, so after two increments, the value is 2.
❓ Predict Output
intermediate2:00remaining
Output of concurrent access with lock
What will be the output of this Swift code using a lock to protect shared state?
Swift
class Counter { private var value = 0 private let lock = NSLock() func increment() { lock.lock() value += 1 lock.unlock() } func getValue() -> Int { lock.lock() let val = value lock.unlock() return val } } let counter = Counter() DispatchQueue.global().async { counter.increment() } DispatchQueue.global().async { counter.increment() } DispatchQueue.global().async { print(counter.getValue()) } // Wait a moment to let async tasks finish Thread.sleep(forTimeInterval: 0.1)
Attempts:
2 left
💡 Hint
The lock ensures only one thread changes the value at a time.
✗ Incorrect
The NSLock serializes access to the value, so both increments happen safely, resulting in 2.
🧠 Conceptual
advanced2:00remaining
Choosing between actors and locks
Which of the following is the best reason to choose actors over locks in Swift concurrency?
Attempts:
2 left
💡 Hint
Think about safety and ease of use in concurrency.
✗ Incorrect
Actors provide automatic serialization of access, making code safer and easier to write compared to manual locks.
❓ Predict Output
advanced2:00remaining
Output difference between actor and lock with async delay
What is the output of this Swift code comparing actor and lock with async delay?
Swift
actor AsyncCounter {
var value = 0
func increment() async {
let current = value
try? await Task.sleep(nanoseconds: 100_000_000) // 0.1 sec
value = current + 1
}
func getValue() -> Int {
return value
}
}
class LockCounter {
private var value = 0
private let lock = NSLock()
func increment() {
lock.lock()
let current = value
Thread.sleep(forTimeInterval: 0.1)
value = current + 1
lock.unlock()
}
func getValue() -> Int {
lock.lock()
let val = value
lock.unlock()
return val
}
}
let actorCounter = AsyncCounter()
let lockCounter = LockCounter()
Task {
await actorCounter.increment()
}
Task {
await actorCounter.increment()
}
DispatchQueue.global().async {
lockCounter.increment()
}
DispatchQueue.global().async {
lockCounter.increment()
}
// Wait for increments
Thread.sleep(forTimeInterval: 0.3)
Task {
print("ActorCounter: \(await actorCounter.getValue())")
print("LockCounter: \(lockCounter.getValue())")
}Attempts:
2 left
💡 Hint
Actors serialize async calls, locks serialize threads.
✗ Incorrect
Both actor and lock serialize increments, so both counters end at 2.
🧠 Conceptual
expert2:00remaining
When to prefer locks over actors
In which scenario is using locks preferred over actors in Swift concurrency?
Attempts:
2 left
💡 Hint
Think about complex locking scenarios involving multiple resources.
✗ Incorrect
Locks allow manual control over multiple locks and can be used to avoid deadlocks with careful design, which actors do not support.