iOS:常见的锁

2020-08-11  本文已影响0人  春暖花已开

加锁是为了防止多条线程同时访问同一块内存,也就是为了线程同步。实现线程同步不仅仅只有加锁的方式,也可以通过 同步串行 来实现。

BaseOperation.h
#import <Foundation/Foundation.h>

@interface BaseOperation : NSObject

///测试
- (void)test;

- (void)otherTest;

///存钱
- (void)saveMoeney;
///取钱
- (void)withdrawMoeney;

@end


@interface SemphoreOperation : BaseOperation
@end


@interface SynchronizedOperation : BaseOperation
@end


@interface NSConditionLockOperation : BaseOperation
@end

///生产者-消费者模式
@interface NSConditionOperation : BaseOperation
@end


@interface NSLockOperation : BaseOperation
@end


@interface os_unfair_lockOperation : BaseOperation
@end


@interface SerialQueueOperation : BaseOperation
@end

///生产者-消费者模式
@interface MutexOperation : BaseOperation
@end
BaseOperation.m
#import "BaseOperation.h"

#pragma mark - BaseOperation
@interface BaseOperation ()

@property (nonatomic, assign) NSInteger money;

@end

@implementation BaseOperation

- (void)test {
    
    self.money = 100;
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i < 5; i++) {
            [self saveMoeney];
        }
    });
    
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i < 5; i++) {
            [self withdrawMoeney];
        }
    });
}

- (void)otherTest { }

- (void)saveMoeney {
    
    NSInteger oldMoney = self.money;
    sleep(.2);
    oldMoney += 50;
    self.money = oldMoney;
    NSLog(@"存钱50,还剩%ld元 - %@", oldMoney, [NSThread currentThread]);
}

- (void)withdrawMoeney {
    
    NSInteger old = self.money;
    sleep(.2);
    old -= 50;
    self.money = old;
    NSLog(@"取钱50后: %ld元 -- %@", self.money, [NSThread currentThread]);
}

@end


#pragma mark - NSConditionOperation
@interface NSConditionOperation ()

@property (nonatomic, strong) NSCondition *condition;
@property (strong, nonatomic) NSMutableArray *dataList;

@end

@implementation NSConditionOperation

- (instancetype)init {
    if (self = [super init]) {
        self.condition = [[NSCondition alloc] init];
        self.dataList = [NSMutableArray array];
    }
    return self;
}

- (void)otherTest {
    [[[NSThread alloc] initWithTarget:self selector:@selector(__consume) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__produce) object:nil] start];
}

///消耗
- (void)__consume {
    
    //加锁
    [self.condition lock];
    
    NSLog(@"__consume - begin");
    if (self.dataList.count == 0) {
        //等待: 阻塞当前线程,直到条件发出信号为止
        [self.condition wait];
    }
    
    [self.dataList removeLastObject];
    NSLog(@"%s %@", __func__, [NSThread currentThread]);
    
    //解锁
    [self.condition unlock];
}

///生产
- (void)__produce {
    
    [self.condition lock];
    
    sleep(1);
    [self.dataList addObject:@"Lynn Zhang"];
    
    NSLog(@"%s %@", __func__, [NSThread currentThread]);
    
    //唤醒等待的线程
    [self.condition signal];
    
    sleep(2);
    [self.condition unlock];
}

@end


#pragma mark - NSConditionLock
@interface NSConditionLockOperation ()

@property (nonatomic, strong) NSConditionLock *conditionLock;

@end

@implementation NSConditionLockOperation

- (instancetype)init {
    if (self = [super init]) {
        //初始化一个NSConditionLock对象
        self.conditionLock = [[NSConditionLock alloc] initWithCondition:1];
    }
    return self;
}

- (void)otherTest {
    [[[NSThread alloc] initWithTarget:self selector:@selector(__one) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__two) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__three) object:nil] start];
}

- (void)__one {
    [self.conditionLock lockWhenCondition:3];
    
    NSLog(@"%s, %@", __func__, [NSThread currentThread]);
    sleep(1);
    
    //解锁后,重置锁的条件
    [self.conditionLock unlockWithCondition:2];
}

- (void)__two {
    [self.conditionLock lockWhenCondition:1];
    
    NSLog(@"%s, %@", __func__, [NSThread currentThread]);
    sleep(1);
    
    [self.conditionLock unlockWithCondition:3];
}

- (void)__three {
    //满足条件时加锁
    [self.conditionLock lockWhenCondition:2];
    
    NSLog(@"%s, %@", __func__, [NSThread currentThread]);
    sleep(1);
    
    [self.conditionLock unlock];
}

@end


#pragma mark - dispatch_semaphore_t
@interface SemphoreOperation ()

@property (nonatomic, strong) dispatch_semaphore_t semaphore_t;

@end

@implementation SemphoreOperation

- (instancetype)init {
    if (self = [super init]) {
        self.semaphore_t = dispatch_semaphore_create(1);
    }
    return self;
}

- (void)saveMoeney {
    
    dispatch_semaphore_wait(self.semaphore_t, DISPATCH_TIME_FOREVER);
    [super saveMoeney];
    dispatch_semaphore_signal(self.semaphore_t);
}

- (void)withdrawMoeney {
    dispatch_semaphore_wait(self.semaphore_t, DISPATCH_TIME_FOREVER);
    [super withdrawMoeney];
    dispatch_semaphore_signal(self.semaphore_t);
}

@end


#pragma mark - synchronized
@implementation SynchronizedOperation

- (void)saveMoeney {
    @synchronized (self) {
        [super saveMoeney];
    }
}

- (void)withdrawMoeney {
    @synchronized (self) {
        [super withdrawMoeney];
    }
}

@end



#pragma mark - NSLockOperation
@interface NSLockOperation ()

@property (nonatomic, strong) NSLock *lock;

@end

@implementation NSLockOperation

- (instancetype)init {
    if (self = [super init]) {
        self.lock = [[NSLock alloc] init];
    }
    return self;
}

- (void)saveMoeney {
    
    [self.lock lock];
    [super saveMoeney];
    [self.lock unlock];
}

- (void)withdrawMoeney {
    
    [self.lock lock];
    [super withdrawMoeney];
    [self.lock unlock];
}

@end


#pragma mark - os_unfair_lockOperation

#import <os/lock.h>

@interface os_unfair_lockOperation ()

@property (nonatomic, assign) os_unfair_lock lock;

@end

@implementation os_unfair_lockOperation

- (instancetype)init {
    if (self = [super init]) {
        self.lock = OS_UNFAIR_LOCK_INIT;
    }
    return self;
}

- (void)saveMoeney {
    
    os_unfair_lock_lock(&_lock);
    [super saveMoeney];
    os_unfair_lock_unlock(&_lock);
}

- (void)withdrawMoeney {
    
    os_unfair_lock_lock(&_lock);
    [super withdrawMoeney];
    os_unfair_lock_unlock(&_lock);
}

@end


#pragma mark - SerialQueueOperation

@interface SerialQueueOperation ()

@property (strong, nonatomic) dispatch_queue_t serialQueue;

@end

@implementation SerialQueueOperation

- (instancetype)init {
    if (self = [super init]) {
        self.serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

- (void)saveMoeney {
    dispatch_sync(self.serialQueue, ^{
        [super saveMoeney];
    });
}

- (void)withdrawMoeney {
    dispatch_sync(self.serialQueue, ^{
        [super withdrawMoeney];
    });
}

@end


#pragma mark - MutexOperation

#import <pthread.h>

@interface MutexOperation()
@property (assign, nonatomic) pthread_mutex_t mutex;
@property (assign, nonatomic) pthread_cond_t cond;
@property (strong, nonatomic) NSMutableArray *data;
@end

@implementation MutexOperation

- (instancetype)init {
    if (self = [super init]) {
        // 初始化属性
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
        // 初始化锁
        pthread_mutex_init(&_mutex, &attr);
        // 销毁属性
        pthread_mutexattr_destroy(&attr);
        
        // 初始化条件
        pthread_cond_init(&_cond, NULL);
        
        self.data = [NSMutableArray array];
    }
    return self;
}

- (void)otherTest {
    [[[NSThread alloc] initWithTarget:self selector:@selector(__consume) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__produce) object:nil] start];
}

//消费
- (void)__consume {
    
    pthread_mutex_lock(&_mutex);
    NSLog(@"__consume - begin");
    
    if (self.data.count == 0) {
        // 等待
        pthread_cond_wait(&_cond, &_mutex);
    }
    
    [self.data removeLastObject];
    NSLog(@"删除了元素");
    
    pthread_mutex_unlock(&_mutex);
}

//生产
- (void)__produce {
    
    pthread_mutex_lock(&_mutex);
    
    sleep(1);
    
    [self.data addObject:@"Test"];
    NSLog(@"添加了元素");
    
    // 信号
    pthread_cond_signal(&_cond);
    // 广播
//    pthread_cond_broadcast(&_cond);
    
    pthread_mutex_unlock(&_mutex);
}

- (void)dealloc {
    pthread_mutex_destroy(&_mutex);
    pthread_cond_destroy(&_cond);
}

@end
上一篇 下一篇

猜你喜欢

热点阅读