目录
前言
这篇文章主要介绍下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 时需要小心处理线程终止的情况。
标签:tickets,OSSpinLock,lock,self,iOS,unfair,线程,自旋,os From: https://blog.csdn.net/ZCC361571217/article/details/141227729