zoukankan      html  css  js  c++  java
  • (五十七)线程的资源共享、单例的实现

    【资源共享的问题】

    例如线程A与B均实现数字Num的加一操作,如果不加以限制,可能A和B先后拿到最初的Num,然后返回Num+1,无法实现Num+1之后再+1。

    【互斥锁】

    使用互斥锁(@synchronized)来解决,让线程A操作时锁住Num,不允许B的读写,直到A操作完并且写回后,再让B进行工作,再锁住Num,直到B操作完毕,再解开锁,类似于上厕所,在厕所内要锁门一样。

    使用@synchronized(self){......}包装在内的为互斥锁的作用范围,会严重降低效率。因此应尽可能的减小范围。不推荐使用。

    【原子锁】

    一般的成员变量都写为nonatomic,即为非原子锁,如果写为atomic就是原子锁,这样的变量只支持多读单写,原子锁限制了写入,对读取没有影响,原子锁的性能影响较小。

    【并发编程的主要目的】

    并发编程最主要的目的是提高性能,让更多的代码同时运行,提高整体性能。

    由于手机端一般不必解决资源抢夺问题,因此一般不会涉及到资源抢夺。

    Tip:线程的休眠方法:

    [NSThread sleepForTimeInterval:0.1f];

    Tip:注意多线程开发永远不要相信一次运行结果。

    【UI都在主线程的原因】

    出于性能考虑,UIKit中绝大多数的类都不是线程安全的,因此,官方要求更新UI的相关操作应该在主线程中执行。


    【单例设计模式】

    如UIApplication、音频播放可以保证音乐一直播放,不随着视图控制器的改变而受到影响。

    再如一些硬件资源,例如加速计、屏幕(UIScreen mainScreen),带有sharedXxx和mainXxx关键字的常常都是单例。

    单例在面试中可能会要求手写。

    单例的实现步骤:

    1.任何对象的alloc方法都会最终调用allocWithZone来实例化,因此重写allocWithZone来实现初始化结果的唯一性。

    2.在allocWihtZone方法中,利用dispatch_once保证调用父类实现初始化的代码只被执行一次,最后返回对象本身。

    为了保证单例不被销毁,使用一个静态指针,静态指针存放在堆中,直到应用程序终止后才会被销毁。

    // 在iOS中,所有对象的内存空间分配,最终都会调用allocWithZone方法
    // 制作单例,需要重写此方法
    + (id)allocWithZone:(struct _NSZone *)zone{
        
        static DemoObj *instance;
        
        // dispatch_once_t是线程安全的
        static dispatch_once_t onceToken;
        // dispatch_once宏可以保证快代码的指令只被执行一次
        dispatch_once(&onceToken, ^{
            // 只会被执行一次
            instance = [super allocWithZone:zone];
        });
        
        return instance;
        
    }

    3.写一个sharedXxx方法用于返回单例对象,由于alloc已经唯一,因此直接在shared方法中返回一个初始化的实例即可:

    + (instancetype)sharedDemoObj{
        
        return [[self alloc] init];
        
    }

    单例的缺点:单例对象一旦被创建,对象指针会存放在静态区,在堆中分配空间,会在应用程序终止后才会释放。

    另一种单例的实现:注意这样是不好的。

    static DemoObj2 *instance;
    
    @implementation DemoObj2
    
    + (instancetype)sharedDemoObj2{
        
        if (!instance) {
            instance = [[self alloc] init];
        }
        
        return instance;
        
    }
    
    @end

    如果仅仅是实现了sharedXxx方法,如果仍使用alloc init仍可以得到多个实例。

    如果有两个线程同时实例化,很可能创建出两个实例来(是线程不安全的)。


  • 相关阅读:
    vue使用elementui合并table
    使用layui框架导出table表为excel
    vue使用elementui框架,导出table表格为excel格式
    前台传数据给后台的几种方式
    uni.app图片同比例缩放
    我的博客
    【C语言】取16进制的每一位
    SharePoint Solution 是如何部署的呢 ???
    无效的数据被用来用作更新列表项 Invalid data has been used to update the list item. The field you are trying to update may be read only.
    SharePoint 判断用户在文件夹上是否有权限的方法
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154193.html
Copyright © 2011-2022 走看看