(五十七)线程的资源共享、单例的实现

【资源共享的问题】

例如线程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仍可以得到多个实例。

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

时间: 2024-09-28 17:40:02

(五十七)线程的资源共享、单例的实现的相关文章

分享一个线程安全的单例模板类

单例模式应该说是最简单的设计模式了.在此分享一个线程安全的单例模板类. template <typename Type> class CSingleton { public: static Type* GetInstance() { // kBeingCreatedMarker用来表示单例实例正在创建过程中. // 此处初始化为1是因为操作系统不会分配地址为1的指针. static const volatile intptr_t kBeingCreatedMarker = 1; // 如果m_

C++实现一个线程安全的单例工厂

我们见到经常有人用 static 局部对象的方式实现了类似单例模式,最近发现一篇文章明确写明 编译器在处理  static局部变量的时候 并不是线程安全的 !!! http://blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx 于是实现了一个单例工厂  并且是线程安全的 #ifndef SINGLETONFACTORY_H #define SINGLETONFACTORY_H #include "windows.h"

设计一个线程安全的单例(Singleton)模式

在设计单例模式的时候,虽然很容易设计出符合单例模式原则的类类型,但是考虑到垃圾回收机制以及线程安全性,需要我们思考的更多.有些设计虽然可以勉强满足项目要求,但是在进行多线程设计的时候.不考虑线程安全性,必然会给我们的程序设计带来隐患.此处,我们不介绍什么是单例模式,也不介绍如何设计简单的设计模式,因为你完全可以在书上或者在博客中找到.此处我们的目的就是设计一个使用的单例模式类.单例模式需要注意与思考的问题: (1)如何仅能实例化一个对象? (2)怎么样设计垃圾回收机制? (3)如何确保线程安全性

OC中线程安全的单例

@implementation MySingleton + (instancetype)sharedInstance { static MySingleton* instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[MySingleton alloc]initPrivate]; }); return instance; } -(id)init { @throw [NS

枚举方式的线程安全的单例

1,枚举 public enum Color { blue, red, yellow } 枚举是会被另外处理的. 枚举只能拥有私有的构造器 枚举类实际上是一个继承Enum的一个final类 枚举类不允许被反序列化,Enum重写了方法 静态代码块中对final变量的值进行初始化 enum类最终是一个final class public final class voctrals.study.whatisspring.test.Color extends java.lang.Enum<voctrals

【Java】设计模型-五种单例模型

一. 什么是单例模式 只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计. 单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在. 单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间: 能够避免由于操作多个实例导致的逻辑错误.如果一个对象有可能贯穿整个应用程序,而且起到了全局统一管理控制的作用,那么单例模式也许是一个值得考虑的选择. 二. 单例模式的特点 1. 单例模式只能有一个实例. 2. 单例类必

页面之间传值方式的总结,五种方式,通知,block,代理,单例,NSUERDEFALUT,

首先代码拿上 1:单例 2:通知 3:代理 4:block方法 5:NSUSERDEFAULT(沙盒文件) 先是单例类: .h文件 @interface DataSource : NSObject @property (nonatomic, strong) NSString *myName;//单例的属性,用于传值 +(DataSource*)sharedDataSource;//建立单例对象 @end .m文件 #import "DataSource.h" @implementati

单例设计模式与类加载顺序详解

单例设计模式几种实现 (测试所用jdk版本1.8.0_20) 第一种: 1 public final class SingleInstance1 { 2 3 private static volatile SingleInstance1 singleInstance = null; 4 /* 5 * 必须定义,防止jvm提供默认构造函数(默认的为public)这样就失去了单例的特性, 6 * 因为可以new一个实例 7 */ 8 private SingleInstance1(){} 9 pub

单例设计模式懒汉式的缺陷

http://icyfenix.iteye.com/blog/575052 IcyFenix 探索设计模式之六——单例模式 设计模式Spring应用服务器多线程JVM 6.单例模式(Singleton Pattern) 前面说提到的五种创建模式,主要解决的问题是如何创建对象,获得产品.而单例模式最要关心的则是对象创建的次数以及何时被创建. Singleton模式可以是很简单的,它的全部只需要一个类就可以完成(看看这章可怜的UML图).但是如果在“对象创建的次数以及何时被创建”这两点上较真起来,S

iOS单例创建的一点疑惑

线程安全的单例常用写法, +(AccountManager *)sharedManager{ static AccountManager *defaultManager = nil; disptch_once_t once; disptch_once(&once,^{ defaultManager = [[self alloc] init]; }); return defaultManager; } 在用的过程中,有点疑惑的点是:static AccountManager *defaultMan