有哪几种多线程技术方案?
| 技术方案 | 简介 | 语言 | 线程生命周期 | 使用评率 |
|---|---|---|---|---|
| pthread | 一套通用的多线程 API,适用于 Unix/Linux/Windows 等系统,跨平台/可移植,使用难度大 | C | 程序员管理 | 几乎不用 |
| NSThread | 使用更加面向对象,简单易用,可直接操作线程对象 | OC | 程序员管理 | 偶尔使用 |
| GCD | 旨在替代 NSThread 等线程技术,充分利用设备的多核 | C | 自动管理 | 经常使用 |
| NSOperation | 基于 GCD(底层是 GCD),比 GCD 多了一些更简单实用的功能,使用更加面向对象 | OC | 自动管理 | 经常使用 |
GCD栅栏函数的读写锁,实现多读单写功能
以下是一个使用栅栏函数实现多读单写的示例:
objective-c
#import <Foundation/Foundation.h>
@interface ReadWriteLock : NSObject
@property (nonatomic, strong) dispatch_queue_t concurrentQueue;
@property (nonatomic, strong) NSMutableDictionary *data;
- (instancetype)init;
- (id)readDataForKey:(NSString *)key;
- (void)writeData:(id)data forKey:(NSString *)key;
@end
@implementation ReadWriteLock
- (instancetype)init {
self = [super init];
if (self) {
self.concurrentQueue = dispatch_queue_create("com.example.readWriteLock", DISPATCH_QUEUE_CONCURRENT);
self.data = [NSMutableDictionary dictionary];
}
return self;
}
- (id)readDataForKey:(NSString *)key {
__block id result;
dispatch_sync(self.concurrentQueue, ^{
result = self.data[key];
});
return result;
}
- (void)writeData:(id)data forKey:(NSString *)key {
dispatch_barrier_async(self.concurrentQueue, ^{
self.data[key] = data;
});
}
@endiOS如何保证线程安全-加锁
1.使用@synchronized关键字:在Objective-C中,可以使用@synchronized关键字来确保同一时间只有一个线程可以访问某个代码块。
objective-c
@synchronized(self) {
// 线程安全的代码块
}2.使用NSLock:NSLock是Foundation框架提供的一种锁机制,可以使用lock和unlock方法来保护临界区。
objective-c
NSLock *lock = [[NSLock alloc] init];
[lock lock];
// 线程安全的代码块
[lock unlock];3.dispatch_semaphore_t:通过信号量机制可以实现加锁的效果,控制并发访问的数量。
objective-c
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 线程安全的代码块
dispatch_semaphore_signal(semaphore);4.dispatch_queue_t + dispatch_barrier_async:在GCD中,可以使用dispatch_barrier_async函数在并发队列中创建一个屏障,确保在屏障之前的任务执行完毕后再执行屏障后的任务。
objective-c
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_barrier_async(concurrentQueue, ^{
// 线程安全的代码块
});5.pthread_mutex_t:使用pthread库中的互斥锁可以实现线程间的互斥访问。
objective-c
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_lock(&mutex);
// 需要保护的代码块
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);atomic一定是线程安全的吗?如何理解
atomic 只保证单个属性的读写操作是原子的。在一系列操作时不是原子性的。实现原理是在setter和getter方法内加@synchronized
Objective-C
- (void)setValue:(id)value {
@synchronized(self) {
_value = value;
}
}
- (id)value {
@synchronized(self) {
return _value;
}
}下面这个操作不是安全的:
Objective-C
// 假设 value 是一个 atomic 属性
self.value = [self.value stringByAppendingString:@"new"];假如有A、B两个线程并发调用上面的操作,AB线程先分别去内存读取value的值,在读的时候因为atomic所以AB不会同时去读,但是A读完之后B就会紧接着去读,所以AB线程可能拿到相同的value值,最后再将结果写入到value,A和B写入value是不会同时发生,但是A写完B就会紧接着去写,并且A和B可能是用相同的值去写。导致结果是 Value+new 而不是 Value+new+new。
