美文网首页活好
ios - 多线程之四:线程锁

ios - 多线程之四:线程锁

作者: 乐意先生 | 来源:发表于2017-05-08 13:46 被阅读42次

假如我们在功能的实现过程中,类中有一个全局变量,我们创建了多个线程去同时改变或者使用这个变量,会出现什么问题?

线程锁就是用来解决多线程之间对资源共享的问题;

思路

在上文《多线程之三》的基础之上进行演示,模仿多个地点进行售票的案例。

代码展示

1:创建按钮

    //问题 : 当多个线程执行某一块相同代码,需要线程锁进行保护
UIButton *btn3 = [UIButton buttonWithType:UIButtonTypeCustom];
btn3.frame = CGRectMake(40, 200, 100, 40);
[btn3 setTitle:@"线程锁" forState:UIControlStateNormal];
[btn3 setBackgroundColor:[UIColor blueColor]];
[btn3 addTarget:self action:@selector(click_lock) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn3];

2:创建售票的管理对象
TicketManager.h

@interface TicketManager : NSObject
- (void) startSale ;
@end

TicketManager.m
首先做一个扩展

  \#define Total 100   //一共一百张票

  @interface TicketManager ()

  @property (nonatomic, assign) int whole;        //总票数
  @property (nonatomic, assign) int surplus;      //剩余票数

  @property (nonatomic, strong) NSThread *thread_SH; //子线程, 上海售票点
  @property (nonatomic, strong) NSThread *thread_BJ; //子线程, 北京售票点
  @property (nonatomic, strong) NSThread *thread_SZ; //子线程, 深圳售票点

  @end

初始化售卖点

@implementation TicketManager

- (instancetype)init
{
self = [super init];
if (self) {
    self.whole = Total;
    self.surplus = Total;
    
    self.thread_SH = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
    self.thread_SH.name = @"上海售票点";
    
    self.thread_BJ = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
    self.thread_BJ.name = @"北京售票点";
    
    self.thread_SZ = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
    self.thread_SZ.name = @"深圳售票点";
}
return self;
}

实现售卖方法

//售票方法
- (void) sale {

while (true) {
    
    if (self.surplus > 0) {  //当还有余票时,就执行卖票
        [NSThread sleepForTimeInterval:1];
        self.surplus = self.surplus - 1;
        NSLog(@"%@ 卖出一张票,剩余:%d",[NSThread currentThread].name, self.surplus);
    }
}

}

三个地方开始同时售票
//开始卖票
- (void) startSale {
[self.thread_SZ start];
[self.thread_BJ start];
[self.thread_SH start];
}

3:在 viewController 里面创建和使用TicketMananger

@property (nonatomic, strong) TicketManager *ticketManager; //票务管理

在 viewDidLoad 中初始化

self.ticketManager = [[TicketManager alloc] init];

在 click_lock 中启动卖票

 NSLog(@"开始卖票");
[self.ticketManager startSale];

4:开始执行,查看打印结果

售票打印.png

根据日志分析:非常明显剩余票数不正确。

接下来我们引入锁的概念来解决这个问题。简单说明下锁是什么概念呢?咱们可以先这样理解:当我在独自使用一个房间的时候,不希望别人同时使用和打扰,这样呢,我们也就可以先对该房间加上锁,然后再使用,在使用完成之后,该房间不归我使用了,我就解开锁,以方便其他人使用、
线程锁有三种方式:
1 : @synchronized
使用方法:将要保护起来的代码块添加到 @synchronized 的括号中包裹起来

//线程锁的第一种方式 :@synchronized
    @synchronized (self) {
        if (self.surplus > 0) {  //当还有余票时,就执行卖票
            [NSThread sleepForTimeInterval:1];
            self.surplus = self.surplus - 1;
            NSLog(@"%@ 卖出一张票,剩余:%d",[NSThread currentThread].name, self.surplus);
        }
    }

2:NSCondition
使用方法:创建了 NSCondition 对象,将保护起来的代码块使用 lock 和 unlock 进行前后包裹;

//线程锁的第二种方式:NSCondition
    if (!self.condition) {
        self.condition = [[NSCondition alloc] init];
    }
    [self.condition lock];
    if (self.surplus > 0) {  //当还有余票时,就执行卖票
        [NSThread sleepForTimeInterval:1];
        self.surplus = self.surplus - 1;
        NSLog(@"%@ 卖出一张票,剩余:%d",[NSThread currentThread].name, self.surplus);
    }
    [self.condition unlock];

3:NSLock
使用方法:创建了 NSLock 对象,将保护起来的代码块使用 lock 和 unlock 进行前后包裹;

//线程锁的第三种方式:NSLock
    if (!self.lock) {
        self.lock = [[NSLock alloc] init];
    }
    [self.lock lock];
    if (self.surplus > 0) {  //当还有余票时,就执行卖票
        [NSThread sleepForTimeInterval:1];
        self.surplus = self.surplus - 1;
        NSLog(@"%@ 卖出一张票,剩余:%d",[NSThread currentThread].name, self.surplus);
    }
    [self.lock unlock];

在我们使用了以上三种线程锁之后的打印结果是怎么样的呢?

线程锁的打印

可以看出打印的结果是健康和良性的;

至此,线程锁的使用先告一段落,我会再后期详细给出三种线程锁的详细特性和使用场景。敬请期待 ~~~~

相关文章

  • 起底多线程同步锁(iOS)

    起底多线程同步锁(iOS) 起底多线程同步锁(iOS)

  • 多线程 (三)iOS中的锁

    ios 多线程--锁

  • OC--各种线程锁

    参考:正确使用多线程同步锁@synchronized()iOS中的锁iOS多线程安全详解iOS 常见知识点(三):...

  • GCD练习

    GCD练习 ios 多线程 GCD : ios 多线程 全剧队列,异步执行 线程间通信 信号量 文件锁 单利模式 ...

  • iOS 多线程

    参考链接 iOS多线程iOS 多线程:『GCD』详尽总结iOS简单优雅的实现复杂情况下的串行需求(各种锁、GCD ...

  • iOS 多线程

    iOS中的各种锁iOS多线程到底不安全在哪里?

  • iOS多线程--并行开发二

    接上文iOS多线程--并行开发一 4、线程同步 说到多线程就不得不提多线程中的锁机制,多线程操作过程中往往多个线程...

  • iOS多线程相关面试题

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程之--NSOperation

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS多线程之--NSThread

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

网友评论

    本文标题:ios - 多线程之四:线程锁

    本文链接:https://www.haomeiwen.com/subject/rammtxtx.html