單列模式:整個程序的生命周期內(nèi),只會創(chuàng)建一個類的實例化對象梳码,而且只要程序還在運行,實例對象就不會釋放暇藏。
·單例模式在運用時濒蒋,單例對象必須保證只有一個實例存在。在我們開發(fā)過程中瓮顽,為了協(xié)調(diào)整個項目的操作围橡,只需要一個實例。比如有登錄的APP中拣播,我們隨時隨地都可能需要用到用戶數(shù)據(jù)收擦,但是不是即用即創(chuàng)建用戶實例炬守,而是在登陸后將用戶數(shù)據(jù)放置一個數(shù)據(jù)文件中,有一個的單列對象統(tǒng)一管理。在整個程序的任何地方曹洽,如果需要訪問用戶的信息辽剧,直接調(diào)用該單例即可。
單例創(chuàng)建
#if 1
//采用線程鎖偷崩,保證只有一個線程訪問
+(instancetype)shareInstance{
Manager *instance = nil;
@synchronized (self) {
if (!instance) {
instance = [[Manager alloc]init];
}
}
return instance;
}
#else
//GCD創(chuàng)建
+(instancetype)shareInstance{
static Manager *instance = nil;
static dispatch_once_t onceTocken;
dispatch_once(&onceTocken,^{
instance = [[Manager alloc]init];
});
return instance;
}
#endif
注解:之前只是看書上這樣寫阐斜,跟著抄罷了诀紊。在一位[西木柚子]前輩的簡書中看明白了,再此十分感謝邻奠。
依上創(chuàng)建單例的實例來說碌宴,如果有兩個線程1,線程2都調(diào)用shareInstance來創(chuàng)建單例呜象,線程1運行到if(八孝!instance)時發(fā)現(xiàn)判斷=0鸠项,instance=nil;就會創(chuàng)建一個instance。如果此時線程2也來到if判斷處楼入,此時的線程1還未完成instance的創(chuàng)建牧抽,所以if(!instance)依然=0阐肤,線程2有創(chuàng)建了一個instance。這樣就會有兩個實例對象愧薛。
解決:
1.使用dispatce_once衫画,dispatce_once保證程序在運行過程中只能被運行1次,假設線程1先執(zhí)行shareInstance方法瞄勾,線程2既不會在執(zhí)行dispatce_once代碼弥激,從而保證只會創(chuàng)建一個實例。
2.互斥鎖
@synchronized (self) {
}
就相當于該過程被上了把鎖四濒,線程2在準備執(zhí)行shareInstance方法時职辨,看到線程1加的互斥鎖,就會進入休眠狀態(tài)喳资,等到線程1執(zhí)行完畢才會被喚醒腾供,然后執(zhí)行if判斷,西施instance 伴鳖!=nil,所以就不會再創(chuàng)建了
**
*互斥鎖會影響性能榜聂,最好選用GCD創(chuàng)建