【问题标题】:What does it mean for something to be thread safe in iOS?iOS 中的线程安全意味着什么?
【发布时间】:2017-05-14 23:42:31
【问题描述】:
我经常遇到关键术语“线程安全”并想知道它的含义。例如,在 Firebase 或 Realm 中,某些对象被认为是“线程安全的”。线程安全究竟意味着什么?
【问题讨论】:
标签:
ios
swift
thread-safety
【解决方案1】:
搜索答案后,我从this网站得到以下信息:
可以从多个线程或并发任务安全地调用线程安全代码,而不会导致任何问题(数据损坏、崩溃等)。非线程安全的代码一次只能在一个上下文中运行。线程安全代码的一个示例是 let a = ["thread-safe"]。该数组是只读的,您可以同时从多个线程中使用它而不会出现问题。另一方面,用 var a = ["thread-unsafe"] 声明的数组是可变的并且可以修改。这意味着它不是线程安全的,因为多个线程可以同时访问和修改数组,结果不可预测。可变且不是固有线程安全的变量和数据结构一次只能从一个线程访问。
【解决方案2】:
如果多个线程可以调用方法或访问对象的成员数据而没有任何问题,则称该对象是线程安全的; “问题”被广泛定义为仅从一个线程访问时偏离行为。
例如,包含代码i = i + 1 的常规整数i 的对象将不是线程安全的,因为两个线程可能会遇到该语句并且一个线程可能会读取原始值i,增加它,然后写回那个增加的值;与另一个线程同时进行。这样,i 将只增加一次,而它本应增加两次。
【解决方案3】:
线程不安全
- 如果任何对象被允许同时被多个线程修改。
线程安全
- 如果任何对象不允许同时被多个线程修改。
一般来说,不可变对象是线程安全的。
【解决方案4】:
iOS 线程安全
[General lock, mutex, semaphore]
Thread safe 表示您的程序按预期运行。这是关于多线程环境的,我们遇到了shared resource 的问题。进而创建:Atomicity, Visibility, Ordering[About]
苹果通过Synchronization Tools为我们提供:
Atomicity
-
Atomic Operations - 基于硬件指令的无锁机制 - 例如 Compare-And-Swap(CAS)[More]...
Visibility
-
Volatile Variable - 从内存中读取值(无缓存)
Ordering
-
Memory Barriers - 保证最新数据[About]
- Objective-C OSMemoryBarrier
同步
-
Locks - 线程可以获得锁而没有其他人可以访问资源。 NSLock.
-
Semaphore 由线程队列、计数器值组成,并具有 wait() 和 signal() api。 Semaphore 允许多个线程(计数器值)在给定时刻处理资源。 DispatchSemaphore,POSIX Semaphore - semaphore_t。 App Group 允许共享 POSIX 信号量
-
Mutex - 互斥,互斥 - 是 Semaphore 的一种类型(允许多个线程),其中 Thread 可以获取它并且能够将块作为单个入侵者使用,所有其他线程将在释放之前被阻止。与lock 的主要区别在于mutex 也适用于进程(不仅是线程)。它还包括memory barrier。
var lock = os_unfair_lock_s()
os_unfair_lock_lock(&lock)
//critical section
os_unfair_lock_unlock(&lock)
NSLock -POSIX Mutex Lock - pthread_mutex_t,Objective-C @synchronized。
let lock = NSLock()
lock.lock()
//critical section
lock.unlock()
-
Recursive lock - Lock Reentrance - 线程可以多次获取锁。 NSRecursiveLock
-
Spin lock - 等待线程根据轮询机制检查它是否可以重复获得锁。这对于小型操作很有用。在这种情况下,线程不会被阻塞,并且不需要像上下文切换这样的昂贵操作
-
[GCD]
-
操作
多线程
【解决方案5】:
举个简单的例子。如果某些内容在多个线程之间共享而没有崩溃等问题,则它是线程安全的。例如,如果您有一个常量 (let value = ["Facebook"]) 并且它在多个线程之间共享,那么它是线程安全的,因为它是只读的并且无法修改。然而,如果您有一个变量 (var value = ["Facebook"]),它可能会在与多个线程共享时导致潜在的崩溃或数据丢失,因为它的数据可以被修改。