2 Comments

Hi Jacob, I have some comments!

First, locks/mutex do make forward progress. Although they can block a thread, the thread holding the lock makes forward progress and is not waiting on future async work, so the whole thing makes forward progress. This is not the case with semaphores which can be signaled from any thread. That's the big difference.

About your performance tests:

- to be fair to atomics and mutex, I would recommend switching to a synchronous operation in processAcrossCores(), the async operation has a lot of potential overhead

- you can use atomic.wrappingAdd() instead of add() as the latter generates slower code

- you can replace ProcessInfo.processInfo.activeProcessorCount with the actual number of performance cores on your machine, that might give you more interesting results

Expand full comment
Jan 23Edited

First, thank you for the in-depth view of Mutex & Atomic.

Just one fix: it looks like the get and set signatures in your cache example are swapped:

get should be:

get(key: Int) -> Int?

set should be:

set(int: Int, key: Int)

Thank you again for the great writing.

P.S. The issue is in the MutexCache

final class MutexCache {

...

func get(int: Int, key: Int) {

cache.withLock {

$0[key]

}

}

...

Expand full comment