Skip to content

有哪几种多线程技术方案?

技术方案简介语言线程生命周期使用评率
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;
    });
}

@end

iOS如何保证线程安全-加锁

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。

世界很美 而你正好有空