我希望能够原子地递增计数器,但我找不到任何关于如何做到这一点的参考。
根据评论添加更多信息:
- 你在用GCD吗?不,我不用GCD。不得不使用队列系统来增加一个数字似乎有些过分了。
- 你了解基本的线程安全吗?是的,否则我不会问原子增量。
- 这个变量是本地的吗?没有
- 是示例级的吗?* 是的,它应该是单个示例的一部分。
我想做这样的事情:
class Counter {
private var mux: Mutex
private (set) value: Int
func increment() {
mux.lock()
value += 1
mux.unlock()
}
}
8条答案
按热度按时间w6lpcovy1#
Low-Level Concurrency APIs:
有一个很长的OSAtomicIncrement和OSAtomicDecrement函数列表,它们允许您以原子方式递增和递减整数值-线程安全,而不必采用锁(或使用队列)。如果您需要从多个线程递增全局计数器以进行统计,则这些可能很有用。如果您所做的只是递增一个全局计数器,那么无障碍的OSAtomicIncrement版本就很好,并且当没有争用时,调用它们的成本很低。
这些函数使用固定大小的整数,您可以根据需要选择32位或64位变体:
(**注意:**正如Erik艾格纳正确注意到的,
OSAtomicIncrement32
和朋友从macOS 10.12/iOS 10.10起已弃用。Xcode 8建议使用<stdatomic.h>
中的函数。然而,这似乎很困难,比较Swift 3: atomic_compare_exchange_strong和https://openradar.appspot.com/27161329。因此,以下基于GCD的方法似乎是目前最好的解决方案。)或者,可以使用GCD队列进行同步。来自“并发编程指南”中的Dispatch Queues:
使用调度队列,您可以将两个任务都添加到串行调度队列,以确保在任何给定时间只有一个任务修改资源。这种基于队列的同步比锁更有效,因为锁在有竞争和无竞争的情况下总是需要昂贵的内核陷阱,而分派队列主要在应用程序的进程空间中工作,只有在绝对必要时才向下调用内核。
对你来说
请参阅Adding items to Swift array across multiple threads causing issues (because arrays aren't thread safe) - how do I get around that?或GCD with static functions of a struct以获取更复杂的示例。这个线程What advantage(s) does dispatch_sync have over @synchronized?也很有趣。
u59ebvdq2#
在这种情况下,队列是一种多余的东西。您可以使用Swift 3中引入的
DispatchSemaphore
来实现此目的,如下所示:类的最新版本是over here。
luaexgnf3#
我知道这个问题已经有点老了,但我最近才偶然发现了同样的问题。在研究了一点并阅读了像http://www.cocoawithlove.com/blog/2016/06/02/threads-and-mutexes.html这样的帖子之后,我想出了这个原子计数器的解决方案。也许它也会帮助其他人。
emeijp434#
详情
解决方案
用法
完整样本
x7rlezfr5#
我改进了@florian的答案,使用了一些重载运算符:
ffscu2ro6#
Swift Atomic
您可以查看Apple托管的
Swift Atomics
库,它支持一般类型Concurrency theory(https://stackoverflow.com/a/59491099/4770877)
rnmwe5a27#
您可以使用
@propertyWrapper
s来完成此操作你可以像这样使用它来原子地递增
如果您想包含一个外部库,请使用Swift Atomics。
enyaitl38#
我们可以使用各种方法来原子地增加swift中的变量,并且已经讨论过here。
此外,Swift还提出了一个SE-0283提案,在Swift中添加原子变量。