zoukankan      html  css  js  c++  java
  • 03-互斥锁和自旋锁

    互斥锁和自旋锁


    互斥锁(Synchronized:)

    • @synchornized(锁){}
      • 任意对象就是锁(常用self)
    • 下一线程会进入sleep状态,会自动从调度池中移除
    • 下一线程在上一线程解锁的时候再放到调度池中
    • 只要被synchronized扩住的代码, 就是被锁住的代码.也就是说, 只要被synchronized{}扩住, 就能实现同一时刻, 只能有一个线程操作
    	@synchornized(self)
    	{
    		//需要加锁的部分
    	}
    

    自旋锁(Atomic:)

    • 下一线程会一直在调度池中等待(不会睡眠)
    @property(nonatomic,assign)int a;
    

    案例(售票员买票)

    技巧

    • 1.@synchronized单词的快速记忆方法
      [NSUserDefaults standardUserDefaults] synchronize + d
    • 2.开发中如果需要加锁, 一般都使用self

    注意

      1. 如果多条线程访问同一个资源, 那么必须使用同一把锁才能锁住
      1. 在开发中, 尽量不要加锁, 如果必须要加锁, 一定记住, 锁的范围不能太大, 哪里会有安全隐患就加在哪里

    需求:三个售票员卖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;
    }
    
  • 相关阅读:
    rust中的arm交叉编译
    Dockerfile简单编写
    docker常用命令
    linux下tf/u盘格式化
    rust查看支持的架构列表
    linux内核版本修改
    cgo引用外部c文件注意1
    redis服务允许外部ip访问开启
    redis密码修改
    setInterval和setTimeout的使用区别
  • 原文地址:https://www.cnblogs.com/KrystalNa/p/4780313.html
Copyright © 2011-2022 走看看