@synchronized (self){
//XXXX
}
Q:使用@synchronized (self)是對(duì)代碼塊的內(nèi)容加鎖葛圃,還是對(duì)self對(duì)象加鎖羽资?
@synchronized(對(duì)象)中的這個(gè)"對(duì)象"是什么,鎖定它是為了什么
——這個(gè)對(duì)象可以是任意一個(gè)object袁滥,作用是以object的內(nèi)存地址映射到系統(tǒng)維護(hù)的一個(gè)遞歸鎖厕九;當(dāng)獲得鎖之后颈娜,其他線程想進(jìn)入同一段代碼時(shí)需要等待,其他線程想使用同一個(gè)object進(jìn)行加鎖時(shí)也需要等待
@synchronized (self)這種寫法會(huì)根據(jù)給定的對(duì)象欣舵,自動(dòng)創(chuàng)建一個(gè)鎖擎鸠,并等待塊中的代碼執(zhí)行完畢缀磕。執(zhí)行到這段代碼結(jié)尾處缘圈,鎖就釋放了劣光。
該同步方法的優(yōu)點(diǎn)就是我們不需要在代碼中顯式的創(chuàng)建鎖對(duì)象,便可以實(shí)現(xiàn)鎖的機(jī)制糟把。然而绢涡,濫用@synchronized (self)則會(huì)降低代碼效率,因?yàn)楣猛粋€(gè)鎖的那些同步塊遣疯,都必須按順序執(zhí)行雄可。若是在self對(duì)象上頻繁加鎖,程序可能要等另一段與此無關(guān)的代碼執(zhí)行完畢缠犀,才能繼續(xù)執(zhí)行當(dāng)前代碼数苫,這樣效率就低了。
注:因?yàn)锧synchronized (self)方法針對(duì)self只有一個(gè)鎖辨液,相當(dāng)于對(duì)于self的所有用到同步塊的地方都是公用同一個(gè)鎖虐急,所以如果有多個(gè)同步塊,則其他的同步塊都要等待當(dāng)前同步塊執(zhí)行完畢才能繼續(xù)執(zhí)行滔迈。
Q:如果在@synchronized (self)的代碼塊中進(jìn)行異步操作止吁,那異步操作未完成,鎖就會(huì)被釋放么燎悍?
代碼塊中進(jìn)行異步操作敬惦,鎖基本等于失效
==========================分割線===========================
在 sellTicket 中鎖定了 self , 如果在 ticket 中沒有用@synchronized(self),就會(huì)在sellTicket中線程運(yùn)行的情況下,運(yùn)行ticket中的線程,
如果用了@synchronized(self) 所有線程就會(huì)一個(gè)一個(gè)運(yùn)行
@property (nonatomic, assign) NSInteger ticket;
- (void)viewDidLoad {
[super viewDidLoad];
_ticket = 50;
[NSThread detachNewThreadSelector:@selector(sellTicket) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(sellTicket) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(ticket123) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(sellTicket) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(sellTicket) toTarget:self withObject:nil];
}
- (void)sellTicket {
while (_ticket > 0) {
[NSThread sleepForTimeInterval:3];
@synchronized (self){
if (_ticket > 0) {
NSLog(@"123");
[NSThread sleepForTimeInterval:3];
self.ticket--;
NSLog(@"%@ %ld ", [NSThread currentThread], _ticket);
}
}
}
}
- (void)ticket123 {
// @synchronized (self) {
for (int i = 0; i < 10; i++) {
[NSThread sleepForTimeInterval:1];
self.ticket--;
NSLog(@"ticker %ld", _ticket);
}
//}
}