iOS中的锁

1.互斥锁

iOS中互斥锁的方式有@synchronized和NSLock,@synchronized块中的代码会加锁保护临界区,使得同时只有一个线程执行其中的代码,当前线程执行完毕之后,其它线程才可以进入执行代码块。NSLock的lock方法和unlock方法之间的部分会加锁保护。

<span style="white-space:pre">	</span>@synchronized(string) {
            //do something
        }
        
        NSLock *lock = [[NSLock alloc] init];
        [lock lock];
        //do something
        [lock unlock];

2.递归锁

递归锁又成为可重入锁,它是指一个线程可以重复地获取某个锁。递归锁可以使用引用计数的方式实现,获取一次锁,相应的引用计数加1,释放一次锁,相应的引用计数减1。

@interface ViewController ()
@property (nonatomic, strong)NSRecursiveLock *recursiveLock;
@end

@implementation ViewController

- (void)countFunction:(NSInteger)count
{
    [self.recursiveLock lock];
    if (count != 0) {
        count--;
        NSLog(@"count is %ld", (long)count);
        [self countFunction:count];
    }
    [self.recursiveLock unlock];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.recursiveLock = [[NSRecursiveLock alloc] init];
    [self countFunction:5];
}

方法countFunction递归调用了自身,如果这个地方使用NSLock将会造成死锁。

3.条件锁

条件锁可以设置条件,满足条件时获取或者释放锁。

@interface ViewController ()
@property (nonatomic, strong)NSConditionLock *conditionLock;
@property (nonatomic, assign)NSInteger count;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.count = 0;
    self.conditionLock = [[NSConditionLock alloc] initWithCondition:0];
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(countSend) object:nil];
    [thread start];
    
    NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(countRecieve) object:nil];
    [thread1 start];
}

- (void)countSend
{
    while (true) {
        [self.conditionLock lockWhenCondition:0];
        self.count++;
        NSLog(@"countSend,the count is %ld", (long)self.count);
        sleep(1);
        [self.conditionLock unlockWithCondition:1];
        if (self.count > 5) {
            break;
        }
    }
}

- (void)countRecieve
{
    while(true) {
        [self.conditionLock lockWhenCondition:1];
        NSLog(@"countRecive,the count is %ld", (long)self.count);
        sleep(1);
        [self.conditionLock unlockWithCondition:0];
        if (self.count > 5) {
            break;
        }
    }
}

@end

上面的代码中,一个线程执行countSend方法改变计数,在改变计数之前先使用条件锁获取资源,改变计数之后改变条件锁的条件,释放资源,它类似于生产者的角色。另外一个线程执行countRecieve方法获取计数,在获取计数之前先视图获取条件锁,获取计数之后,改变条件锁的条件,释放资源,它类似于消费者的角色。

4.读写锁

在读者写者问题中,写操作是独占的,只能有一个线程同时进行写操作,读操作是共享的,可以有多个线程同时进行读操作。读写锁正是可以实现这种方式的要求,读写锁允许多个线程并发的读取,因而具有更高的并发性,它适用于读操作多于写操作的情况。GCD可以用于实现读写锁。

@interface ReadwriteString : NSObject
@property (nonatomic, strong)NSString *string;
@property (nonatomic, strong)dispatch_queue_t queue;
@end

@implementation ReadwriteString

- (instancetype)init
{
    if (self = [super init]) {
        _queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    }
    return self;
}

- (void)modifyString:(NSString *)string
{
    dispatch_barrier_async(self.queue, ^{
        _string = string;
    });
}

- (NSString *)acquireString
{
    __block NSString *string = nil;
    dispatch_sync(self.queue, ^{
        string = self.string;
    });
    return string;
}

@end
代码中init方法创建了并行队列,modifyString方法在并行队列中使用了

dispatch_barrier_async,这个接口保证之前的任务完成之后在执行dispatch_barrier_async对应的block,之后的任务在dispatch_barrier_async对应的block完成后才执行。如果对string进行写操作,此时无法同时进行读操作,而读操作可以由多个任务并发执行的,这样就实现了一个读写锁。

5.自旋锁

相比于互斥所,自旋锁不会使得其它线程进入睡眠,在一个线程获取自旋锁以后,其它线程会不停地执行while循环知道获取资源。自旋锁省去了睡眠系统调用因而它有着较高的执行效率,自旋锁的缺点是如果一个线程迟迟不释放锁,其它线程因为不停执行循环而消耗CPU。自旋锁适合于临界区资源处理速度很快的场合。

#import "ViewController.h"
#import <libkern/OSAtomic.h>

@interface ViewController ()
{
    OSSpinLock _lock;
}
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    OSSpinLockLock(&_lock);
    //do something
    OSSpinLockUnlock(&_lock);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS,可以使用互斥锁来实现线程间的互斥访问,保护共享资源的安全。互斥锁的实现原理可以分为两个层面:内核层面和用户层面。 1. 内核层面的互斥锁实现原理: - POSIX互斥锁:在iOS,使用POSIX标准的互斥锁pthread_mutex_t来实现。它是基于内核提供的原语实现的,通过系统调用来管理的状态。当一个线程请求时,如果已经被占用,则该线程会被阻塞,并进入等待状态。当持有的线程释放时,等待队列的一个线程会被唤醒,获取到继续执行。 2. 用户层面的互斥锁实现原理: - 自旋锁自旋锁是一种忙等待的机制,它通过循环检查的状态,直到获取到为止。在iOS,可以使用OSSpinLock来实现自旋锁。当一个线程请求时,如果已经被占用,则该线程会一直循环检查的状态,直到获取到后才继续执行。自旋锁适用于临界区代码执行时间短暂,且争用的线程数较少的情况。 - 互斥锁NSLockNSRecursiveLockNSConditionLock):在iOS,还提供了一些高级的互斥锁类,如NSLockNSRecursiveLockNSConditionLock。这些类是基于底层的pthread_mutex_t实现的,提供了更方便的API和更高级的功能。NSLockNSRecursiveLock互斥锁,可以保护临界区代码的互斥访问。NSRecursiveLock允许同一个线程对进行多次加,避免死NSConditionLock是一种条件,可以在特定条件满足时才允许访问临界区代码。 需要注意的是,使用互斥锁时,应遵循良好的加和解的原则,避免死和资源泄漏等问题。同时,在高并发的场景,也可以考虑使用其他更高级的同步机制,如信号量(dispatch_semaphore)或读写锁(pthread_rwlock_t),以满足不同的需求。 希望以上解答对你有所帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值