說到多線程就不得不提多線程中的鎖機制剿牺,多線程操作過程中往往多個線程是并發(fā)執(zhí)行的旨袒,同一個資源可能被多個線程同時訪問狮崩,造成資源搶奪励翼,這個過程中如果沒有鎖機制往往會造成重大問題。舉例來說咏窿,每年春節(jié)都是一票難求,在12306買票的過程中,成百上千的票瞬間就消失了缠黍。不妨假設某輛車有1千張票,同時有幾萬人在搶這列車的車票药蜻,順利的話前面的人都能買到票瓷式。但是如果現(xiàn)在只剩下一張票了,而同時還有幾千人在購買這張票语泽,雖然在進入購票環(huán)節(jié)的時候會判斷當前票數(shù)贸典,但是當前已經(jīng)有100個線程進入購票的環(huán)節(jié),每個線程處理完票數(shù)都會減1,100個線程執(zhí)行完當前票數(shù)為-99踱卵,遇到這種情況很明顯是不允許的廊驼。
要解決資源搶奪問題在iOS中有常用的有兩種方法:一種是使用NSLock同步鎖据过,另一種是使用@synchronized代碼塊。兩種方法實現(xiàn)原理是類似的妒挎,只是在處理上代碼塊使用起來更加簡單(C#中也有類似的處理機制synchronized和lock)绳锅。
多線程的安全隱患
資源共享
一塊資源可能會被多個線程共享,也就是多個線程可能會訪問同一塊資源酝掩。比如多個線程訪問同一個對象鳞芙、同一個變量、同一個文件期虾。當多個線程訪問同一塊資源時原朝,很容易引發(fā)數(shù)據(jù)錯亂和數(shù)據(jù)安全問題。
-
(void)test
{
//默認有20張票
leftTicketsCount = 10;//開啟多個線程彻消,模擬售票員售票
NSThread *thread1=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
thread1.name=@"售票員A";NSThread *thread2=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
thread2.name=@"售票員B";NSThread *thread3=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
thread3.name=@"售票員C";//開啟線程
[thread1 start];
[thread2 start];
[thread3 start];
} -
(void)sellTickets
{
while (1) {
//1.先檢查票數(shù)
int count = leftTicketsCount;
if (count>0) {
//暫停一段時間
[NSThread sleepForTimeInterval:0.002];//2.票數(shù)-1 leftTicketsCount= count-1; //獲取當前線程 NSThread *current=[NSThread currentThread]; NSLog(@"%@--賣了一張票竿拆,還剩余%d張票", current.name, leftTicketsCount); } else { //退出線程 [NSThread exit]; }
}
}
</code></pre>
打印結果:
如何解決
1.使用互斥鎖
格式:
@synchronized(鎖對象) {
// 需要鎖定的代碼
}
注意:鎖定1份代碼只用1把鎖宾尚,用多把鎖是無效的
<pre><code>
-
(void)sellTickets
{
while (1) {
@synchronized(self){//加一把鎖
//1.先檢查票數(shù)
int count = leftTicketsCount;
if (count>0) {
//暫停一段時間
[NSThread sleepForTimeInterval:0.002];//2.票數(shù)-1 leftTicketsCount= count-1; //獲取當前線程 NSThread *current=[NSThread currentThread]; NSLog(@"%@--賣了一張票丙笋,還剩余%d張票", current.name, leftTicketsCount); } else { //退出線程 [NSThread exit]; } }
}
}
</code></pre>
打印結果:
互斥鎖的優(yōu)缺點
優(yōu)點:能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問題
缺點:需要消耗大量的CPU資源
互斥鎖的使用前提:多條線程搶奪同一塊資源
相關專業(yè)術語:線程同步,多條線程按順序地執(zhí)行任務
互斥鎖,就是使用了線程同步技術
2.原子和非原子屬性
OC在定義屬性時有nonatomic和atomic兩種選擇
atomic:原子屬性煌贴,為setter方法加鎖(默認就是atomic)
nonatomic:非原子屬性御板,不會為setter方法加鎖
atomic加鎖原理:
<pre><code>
@property (assign, atomic) int age;
- (void)setAge:(int)age
{
@synchronized(self) {
_age = age;
}
}
</code></pre>
nonatomic和atomic對比
- atomic:線程安全,需要消耗大量的資源
- nonatomic:非線程安全牛郑,適合內存小的移動設備