互斥锁和自旋锁
互斥锁(Synchronized:)
- @synchornized(锁){}
- 下一线程会进入sleep状态,会自动从调度池中移除
- 下一线程在上一线程解锁的时候再放到调度池中
- 只要被synchronized扩住的代码, 就是被锁住的代码.也就是说, 只要被synchronized{}扩住, 就能实现同一时刻, 只能有一个线程操作
@synchornized(self)
{
//需要加锁的部分
}
自旋锁(Atomic:)
@property(nonatomic,assign)int a;
案例(售票员买票)
技巧
- 1.@synchronized单词的快速记忆方法
[NSUserDefaults standardUserDefaults] synchronize + d
- 2.开发中如果需要加锁, 一般都使用self
注意
-
- 如果多条线程访问同一个资源, 那么必须使用同一把锁才能锁住
-
- 在开发中, 尽量不要加锁, 如果必须要加锁, 一定记住, 锁的范围不能太大, 哪里会有安全隐患就加在哪里
需求:三个售票员卖100张票
@interface ViewController ()
@property (nonatomic, strong) NSThread *thread1; /**< 售票员1 */
@property (nonatomic, strong) NSThread *thread2; /**< 售票员2 */
@property (nonatomic, strong) NSThread *thread3; /**< 售票员2 */
@property (nonatomic, assign)NSUInteger totalCount; /**< 票的总数 */
@property (nonatomic, strong) NSObject *lockObj; /**< 锁 */
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 0.初始化票数
self.totalCount = 100;
// 1.创建3个售票员
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
thread1.name = @"售票员1";
self.thread1 = thread1;
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
thread2.name = @"售票员2";
self.thread2 = thread2;
NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
thread3.name = @"售票员3";
self.thread3 = thread3;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 2.让3个售票员同事售票
[self.thread1 start];
[self.thread2 start];
[self.thread3 start];
}
// 售票方法
- (void)saleTicket
{
while (1) {
//增加用户体验
NSLog(@"欢迎光临");
// NSObject lockObj = [[NSObject alloc] init];
//开发中锁对象可以用self
@synchronized(self){ // 锁住
// 1.查询剩余的票数
NSUInteger count = self.totalCount;
// 2.判断是否还有余票
if (count > 0) {
// 线程1 100
[NSThread sleepForTimeInterval:0.1];
// 2.1卖票
self.totalCount = count - 1; // 99
NSLog(@"%@卖了一张票, 还剩%zd票", [NSThread currentThread].name, self.totalCount);
}else
{
// 3.提示客户, 没有票了
NSLog(@"对不起, 没有票了");
break;
}
} // 解锁
}
}
//必须是同一个锁
- (NSObject *)lockObj
{
if (!_lockObj) {
_lockObj = [[NSObject alloc] init];
}
return _lockObj;
}