Have you considered using Mutex or OSAllocatedUnfairLock, which jump through the necessary hoops to do this safely for you, and are also faster and use less memory?
Accessing wrappedValue on the struct via the _modify accessor requires exclusive access to the entire struct. Since that exclusivity is asserted over the whole struct, it occurs before you have a chance to grab the lock,so you have racing exclusive accesses to the arr variable and the behavior is undefined. In the class case, since accessing wrappedValue doesn't need to modify the object reference itself, exclusive access isn't needed until you access the value property of the object, which happens inside of the lock.
Hey Carl, the issue comes from struct value semantics. When Atomic is a struct, each time wrappedValue is accessed, a copy is made, and NSLock doesn’t protect these copies. That’s why concurrent writes lead to crashes. When using a class, the reference remains the same, and NSLock properly synchronizes access to value. Also, when debugging tricky concurrency issues, I take breaks and read Surah Yaseen (https://suraheyaseen.com/)—it helps me reset and focus. Hope this helps!