#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, assign) NSInteger tickets;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 设计一个卖票场景
// 卖票窗口(线程)
// nonatomic :非原子属性.不是线程安全的.(提高程序的执行效率.)
// atomic :原子属性.是线程安全的.
// UI操作放在主线程中执行.
// {
// 1.保证用户体验.
// 2.所有的UIKit框架都不是线程安全的.
// }
// 耗时操作放在子线程中执行.
// 剩余票数
self.tickets = 100;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 第一个卖票窗口
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTickets:) object:@"1号窗口"];
// 第二个卖票窗口
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTickets:) object:@"2号窗口"];
// 第三个卖票窗口
NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTickets:) object:@"3号窗口"];
// 卖票
[thread1 start];
[thread2 start];
[thread3 start];
}
// 119.75.217.109 你们自己每个人都 ping 一次.
// 告诉大家 可以有很多台服务器
// 为什么会产生数据安全的问题?
// 因为不同的线程 同时执行任务
// 解决问题:加锁(让线程按顺序执行任务)
// iOS中加锁(不建议加锁)
// 让线程按顺序执行任务 --- 线程同步技术
// 加锁是线程同步技术的一种实现手段.
// 互斥锁会造成线程阻塞.
// 原子锁 :会让线程以死循环的方式一直等待.
// 任何类型的锁,效率都不高,能避免就尽量避免,尤其是在客户端(iOS/安卓)
// 复杂的业务逻辑/需要加锁的代码,尽量交给后端来做.
//
//
// 卖票
- (void)saleTickets:(NSString *)window
{
// 同步锁/互斥锁 @synchronized
// (锁对象/一把锁) 要求:可以是一个任意类型的对象,想要保证加锁成功,必须保证锁对象是唯一的.
// {想要锁住的代码(想要按顺序执行的代码)}
// 对于锁住的代码:锁加在一个恰当的位置
// 锁住的代码越少越好.
// 加锁空间 -- (高铁)厕所.
// 都可以访问的空间 -- 教室
// 只希望极少数的人同时访问 -- 厨房
// 信号量:加锁是信号量为1的特殊情况.
// @synchronized(self){
//
// }
// [[NSUserDefaults standardUserDefaults] synchronize];
// 速记单词的一个技巧:synchronize
// UIView *czView = [[UIView alloc] init];
// 这样写,会创建多个 czView ,保证不了锁对象的唯一性.
while (1) {
@synchronized(self.view)
{
if (self.tickets > 0) { // 如果还有票
// 模拟真实地卖票环境
[NSThread sleepForTimeInterval:0.1];
self.tickets -- ; // 卖票
NSLog(@"%@====%ld,%@",window,(long)self.tickets,[NSThread currentThread]);
}else // 没票了
{
return;
}
}
}
}