iOS中的自旋锁(OSSpinLock)

目录

前言

1.概念

一、基本用法

 1.初始化

2.锁定和解锁

二、示例代码

三、os_unfair_lock的优缺点

1.优点

1.防止优先级反转

2.性能高

3.轻量级

2.缺点

1.不支持递归锁定

2.线程杀死时不自动释放


前言

        这篇文章主要介绍下OSSpinLock(自旋锁)。

1.概念

        os_unfair_lock 是 iOS 和 macOS 中的锁定机制,旨在替代已弃用的 OSSpinLock。os_unfair_lock 解决了 OSSpinLock 存在的优先级反转问题,同时保持了较高的性能和低开销。它适用于在多线程环境中保护共享资源,并且是轻量级锁定方案。

一、基本用法

        os_unfair_lock 的 API 非常简单,包含初始化、锁定、解锁等操作。它的使用方式与 OSSpinLock 类似,但具有更好的性能和安全性。

 1.初始化

os_unfair_lock unfairLock = OS_UNFAIR_LOCK_INIT;

2.锁定和解锁

        锁定和解锁的主要API如下:

void os_unfair_lock_lock(os_unfair_lock_t lock);
void os_unfair_lock_unlock(os_unfair_lock_t lock);
bool os_unfair_lock_trylock(os_unfair_lock_t lock);

        os_unfair_lock_lock:获取锁。如果锁已经被其他线程持有,当前线程会被阻塞,直到锁可用。

        os_unfair_lock_unlock:释放锁。

        os_unfair_lock_trylock:尝试获取锁。如果成功,返回 true;如果锁已经被其他线程持有,返回 false。

二、示例代码

        我们可以使用os_fair_lock实现一个买票和卖票的例子。在这个例子中,我们创建了一个票务系统,多个线程进行同时买票和卖票操作,使用os_unfair_lock来保证线程安全。

        以下是一个使用 os_unfair_lock 的简单示例:        

#import <Foundation/Foundation.h>
#import <os/lock.h>

@interface TicketSystem : NSObject

@property (nonatomic, assign) int tickets;
@property (nonatomic, assign) os_unfair_lock lock;

- (instancetype)initWithTicketCount:(int)count;
- (void)sellTicket;
- (void)buyTicket;

@end

@implementation TicketSystem

- (instancetype)initWithTicketCount:(int)count {
    self = [super init];
    if (self) {
        _tickets = count;
        _lock = OS_UNFAIR_LOCK_INIT;
    }
    return self;
}

- (void)sellTicket {
    os_unfair_lock_lock(&_lock);
    if (self.tickets > 0) {
        self.tickets--;
        NSLog(@"Ticket sold. Remaining tickets: %d", self.tickets);
    } else {
        NSLog(@"No tickets left to sell.");
    }
    os_unfair_lock_unlock(&_lock);
}

- (void)buyTicket {
    os_unfair_lock_lock(&_lock);
    if (self.tickets < 100) { // 假设最大票数为100
        self.tickets++;
        NSLog(@"Ticket bought. Total tickets: %d", self.tickets);
    } else {
        NSLog(@"Max tickets reached. Cannot buy more.");
    }
    os_unfair_lock_unlock(&_lock);
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        TicketSystem *ticketSystem = [[TicketSystem alloc] initWithTicketCount:50];
        
        // 模拟卖票线程
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            for (int i = 0; i < 30; i++) {
                [ticketSystem sellTicket];
                [NSThread sleepForTimeInterval:0.1]; // 模拟卖票操作的耗时
            }
        });
        
        // 模拟买票线程
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            for (int i = 0; i < 30; i++) {
                [ticketSystem buyTicket];
                [NSThread sleepForTimeInterval:0.15]; // 模拟买票操作的耗时
            }
        });
        
        // 主线程等待一段时间以便子线程完成操作
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
    }
    return 0;
}

        在这个示例中,

1. TicketSystem类:

       这个ticketSystem类用来管理票的数量。

        tickets 属性用于记录当前票的数量。

        lock 属性是一个 os_unfair_lock,用于确保 sellTicket 和 buyTicket 方法在多线程环境下的安全性。

2. sellTicket方法:

         该方法模拟了卖票的操作,先加锁,然后检查是否有票,如果有票则减去一张票,并打印当前剩余票数。

        最后释放锁。

3. buyTicket方法:

        该方法模拟了买票的操作,先加锁,然后检查当前票数是否少于最大票数,如果满足条件则加一张票,并打印当前总票数。

        最后释放锁。

4.多线程操作:

        使用 dispatch_async 创建两个并发线程,一个用于模拟卖票,一个用于模拟买票。        

        通过 NSThread sleepForTimeInterval 模拟操作的耗时,确保线程之间的竞争。

5.主线程等待:

        为了让子线程完成操作,主线程使用 NSRunLoop 等待一段时间。

三、os_unfair_lock的优缺点

1.优点

1.防止优先级反转

        os_unfair_lock 解决了 OSSpinLock 中的优先级反转问题,当高优先级线程需要获取锁时,系统会尽快让低优先级线程释放锁。

2.性能高

        os_unfair_lock 在锁竞争较少的情况下具有较高的性能,开销较低。

3.轻量级

        与更复杂的同步机制(如 pthread_mutex)相比,os_unfair_lock 更加轻量,适合需要快速锁定和解锁的场景。

2.缺点

1.不支持递归锁定

        os_unfair_lock 不支持递归锁定(即同一线程多次锁定同一锁)。如果需要递归锁定功能,建议使用其他同步机制,如 NSRecursiveLock。

2.线程杀死时不自动释放

        如果持有锁的线程被强制终止,锁不会自动释放,可能导致死锁。因此,在使用 os_unfair_lock 时需要小心处理线程终止的情况。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫柱子哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值