iOS¶àḬ̈߳²È«µÄ¸ÅÄîÔÚºÜ¶àµØ·½¶¼»áÓöµ½£¬ÎªÊ²Ã´²»°²È«£¬²»°²È«ÓÖ¸ÃÔõôȥ¶¨Ò壬ÆäʵÊǸöÖµµÃÉµÄ»°Ìâ¡£
¹²Ïí״̬£¬¶àÏ̹߳²Í¬·ÃÎÊij¸ö¶ÔÏóµÄproperty£¬ÔÚiOS±à³ÌÀïÊÇºÜÆÕ±éµÄʹÓó¡¾°£¬ÎÒÃǾʹÓPropertyµÄ¶àḬ̈߳²È«ËµÆð¡£
Property
µ±ÎÒÃÇÌÖÂÛproperty¶àḬ̈߳²È«µÄʱºò£¬ºÜ¶àÈ˶¼ÖªµÀ¸øproperty¼ÓÉÏatomic attributeÖ®ºó£¬¿ÉÒÔÒ»¶¨³Ì¶ÈµÄ±£Õ϶àḬ̈߳²È«£¬ÀàËÆ£º
@property (atomic, strong) NSString* userName; |
ÊÂÇ鲢ûÓп´ÉÏÈ¥Õâô¼òµ¥£¬Òª·ÖÎöpropertyÔÚ¶àÏ̳߳¡¾°ÏµıíÏÖ£¬ÐèÒªÏȶÔpropertyµÄÀàÐÍ×öÇø·Ö¡£
ÎÒÃÇ¿ÉÒÔ¼òµ¥µÄ½«property·ÖΪֵÀàÐͺͶÔÏóÀàÐÍ£¬ÖµÀàÐÍÊÇÖ¸primitive type£¬°üÀ¨int,
long, boolµÈ·Ç¶ÔÏóÀàÐÍ£¬ÁíÒ»ÖÖÊǶÔÏóÀàÐÍ£¬ÉùÃ÷ΪָÕ룬¿ÉÒÔÖ¸Ïòij¸ö·ûºÏÀàÐͶ¨ÒåµÄÄÚ´æÇøÓò¡£
ÉÏÊö´úÂëÖÐuserNameÃ÷ÏÔÊǸö¶ÔÏóÀàÐÍ£¬µ±ÎÒÃÇ·ÃÎÊuserNameµÄʱºò£¬·ÃÎʵÄÓпÉÄÜÊÇuserName±¾Éí£¬Ò²ÓпÉÄÜÊÇuserNameËùÖ¸ÏòµÄÄÚ´æÇøÓò¡£
±ÈÈ磺
ÊÇÔÚ¶ÔÖ¸Õë±¾Éí½øÐи³Öµ¡£¶ø
[self.userName rangeOfString:@"peak"]; |
ÊÇÔÚ·ÃÎÊÖ¸ÕëÖ¸ÏòµÄ×Ö·û´®ËùÔÚµÄÄÚ´æÇøÓò£¬Õâ¶þÕß²¢²»Ò»Ñù¡£
ËùÒÔÎÒÃÇ¿ÉÒÔ´óÖÂÉϽ«property·ÖΪÈýÀࣺ

·ÖÍêÀàÖ®ºó£¬ÎÒÃÇÐèÒªÃ÷°×ÕâÈýÀàpropertyµÄÄÚ´æÄ£ÐÍ¡£
Memory Layout
µ±ÎÒÃÇÌÖÂÛ¶àḬ̈߳²È«µÄʱºò£¬ÆäʵÊÇÔÚÌÖÂÛ¶à¸öÏß³Ìͬʱ·ÃÎÊÒ»¸öÄÚ´æÇøÓòµÄ°²È«ÎÊÌâ¡£Õë¶Ôͬһ¿éÇøÓò£¬ÎÒÃÇÓÐÁ½ÖÖ²Ù×÷£¬¶Á£¨load£©ºÍд£¨store£©£¬¶ÁºÍдͬʱ·¢ÉúÔÚͬһ¿éÇøÓòµÄʱºò£¬¾ÍÓпÉÄܳöÏÖ¶àÏ̲߳»°²È«¡£ËùÒÔÕ¹¿ªÌÖÂÛ֮ǰ£¬ÏÈÒªÃ÷°×ÉÏÊöÈýÖÖpropertyµÄÄÚ´æÄ£ÐÍ£¬¿ÉÓÃÈçÏÂͼʾ£º

ÒÔ64λϵͳΪÀý£¬Ö¸ÕëNSString*ÊÇ8¸ö×Ö½ÚµÄÄÚ´æÇøÓò£¬int countÊǸö4×Ö½ÚµÄÇøÓò£¬¶ø@¡°Peak¡±ÊÇÒ»¿é¸ù¾Ý×Ö·û´®³¤¶È¶ø¶¨µÄÄÚ´æÇøÓò¡£
µ±ÎÒÃÇ·ÃÎÊpropertyµÄʱºò£¬Êµ¼ÊÉÏÊÇ·ÃÎÊÉÏͼÖÐÈý¿éÄÚ´æÇøÓò¡£
ÊÇÐ޸ĵÚÒ»¿éÇøÓò¡£
ÊÇÔÚÐ޸ĵڶþ¿éÇøÓò¡£
[self.userName rangeOfString:@"peak"]; |
ÊÇÔÚ¶ÁÈ¡µÚÈý¿éÇøÓò¡£
²»°²È«µÄ¶¨Òå
Ã÷°×ÁËpropertyµÄÀàÐÍÒÔ¼°ËûÃǶÔÓ¦µÄÄÚ´æÄ£ÐÍ£¬ÎÒÃÇÔÙÀ´¿´¿´²»°²È«µÄ¶¨Òå¡£WikipediaÈçÊÇ˵£º
A piece of code is thread-safe if it manipulates shared data structures only in a manner that guarantees safe execution by multiple threads at the same time |
Õâ¶Î¶¨Òå¿´ÆðÀ´»¹ÊÇÓеã³éÏó£¬ÎÒÃÇ¿ÉÒÔ½«¶àÏ̲߳»°²È«½âÊÍΪ£º¶àÏ̷߳ÃÎÊʱ³öÏÖÒâÁÏÖ®ÍâµÄ½á¹û¡£Õâ¸öÒâÁÏÖ®ÍâµÄ½á¹û°üº¬¼¸ÖÖ³¡¾°£¬²»Ò»¶¨ÊÇÖ¸crash£¬ºóÃæÔÙÒ»Ò»·ÖÎö¡£
ÏÈÀ´¿´Ï¶àÏß³ÌÊÇÈçºÎͬʱ·ÃÎÊÄÚ´æµÄ¡£²»¿¼ÂÇCPU cache¶Ô±äÁ¿µÄ»º´æ£¬ÄÚ´æ·ÃÎÊ¿ÉÒÔÓÃÏÂͼ±íʾ£º

´ÓÉÏͼÖпÉÒÔ¿´³ö£¬ÎÒÃÇÖ»ÓÐÒ»¸öµØÖ·×ÜÏߣ¬Ò»¸öÄÚ´æ¡£¼´Ê¹ÊÇÔÚ¶àÏ̵߳Ļ·¾³Ï£¬Ò²²»¿ÉÄÜ´æÔÚÁ½¸öÏß³Ìͬʱ·ÃÎÊÒ»¿éÄÚ´æÇøÓòµÄ³¡¾°£¬ÄÚ´æµÄ·ÃÎÊÒ»¶¨ÊÇͨ¹ýÒ»¸öµØÖ·×ÜÏß´®ÐÐÅŶӷÃÎʵģ¬ËùÒÔÔÚ¼ÌÐøºóÐøÖ®Ç°£¬ÎÒÃÇÏÈÒªÃ÷È·¼¸¸ö½áÂÛ£º
½áÂÛÒ»£ºÄÚ´æµÄ·ÃÎÊʱ´®Ðе쬲¢²»»áµ¼ÖÂÄÚ´æÊý¾ÝµÄ´íÂÒ»òÕßÓ¦ÓõÄcrash¡£
½áÂÛ¶þ£ºÈç¹û¶Áд£¨load or store£©µÄÄڴ泤¶ÈСÓÚµÈÓÚµØÖ·×ÜÏߵij¤¶È£¬ÄÇô¶ÁдµÄ²Ù×÷ÊÇÔ×ӵģ¬Ò»´ÎÍê³É¡£±ÈÈçbool£¬int£¬longÔÚ64λϵͳϵĵ¥´Î¶Áд¶¼ÊÇÔ×Ó²Ù×÷¡£
½ÓÏÂÀ´ÎÒÃǸù¾ÝÉÏÃæÈýÖÖpropertyµÄ·ÖÀàÖðÒ»¿´Ï¶àÏ̵߳IJ»°²È«³¡¾°¡£
ÖµÀàÐÍProperty
ÏÈÒÔBOOLÖµÀàÐÍΪÀý£¬µ±ÎÒÃÇÓÐÁ½¸öÏ̷߳ÃÎÊÈçÏÂpropertyµÄʱºò£º
@property (nonatomic, assgin) BOOL isDeleted;
//thread 1
bool isDeleted = self.isDeleted;
//thread 2
self.isDeleted = false; |
Ïß³Ì1ºÍÏß³Ì2£¬Ò»¸ö¶Á(load)£¬Ò»¸öд(store)£¬¶ÔÓÚBOOL isDeletedµÄ·ÃÎÊ¿ÉÄÜÓÐÏȺóÖ®·Ö£¬µ«Ò»¶¨ÊÇ´®ÐÐÅŶӵġ£¶øÇÒÓÉÓÚBOOL´óСֻÓÐ1¸ö×Ö½Ú£¬64λϵͳµÄµØÖ·×ÜÏß¶ÔÓÚ¶ÁдָÁî¿ÉÒÔÖ§³Ö8¸ö×ֽڵij¤¶È£¬ËùÒÔ¶ÔÓÚBOOLµÄ¶ÁºÍд²Ù×÷ÎÒÃÇ¿ÉÒÔÈÏΪÊÇÔ×ӵģ¬ËùÒÔµ±ÎÒÃÇÉùÃ÷BOOLÀàÐ͵ÄpropertyµÄʱºò£¬´ÓÔ×ÓÐԵĽǶȿ´£¬Ê¹ÓÃatomicºÍnonatomic²¢Ã»ÓÐʵ¼ÊÉϵÄÇø±ð£¨µ±È»Èç¹ûÖØÔØÁËgetter·½·¨¾ÍÁíµ±±ðÂÛÁË£©¡£
Èç¹ûÊÇintÀàÐÍÄØ£¿
@property (nonatomic, assgin) int count;
//thread 1
int curCount = self.count;
//thread 2
self.count = 1; |
ͬÀíintÀàÐͳ¤¶ÈΪ4×Ö½Ú£¬¶ÁºÍд¶¼¿ÉÒÔͨ¹ýÒ»¸öÖ¸ÁîÍê³É£¬ËùÒÔÀíÂÛÉ϶ÁºÍд²Ù×÷¶¼ÊÇÔ×ӵġ£´Ó·ÃÎÊÄÚ´æµÄ½Ç¶È¿´nonatomicºÍatomicÒ²²¢Ã»ÓÐÊ²Ã´Çø±ð¡£
atomicµ½µ×ÓÐʲôÓÃÄØ£¿¾ÝÎÒËùÖª£¬Óô¦Óжþ£º
Óô¦Ò»£º Éú³ÉÔ×Ó²Ù×÷µÄgetterºÍsetter¡£
ÉèÖÃatomicÖ®ºó£¬Ä¬ÈÏÉú³ÉµÄgetterºÍsetter·½·¨Ö´ÐÐÊÇÔ×ӵġ£Ò²¾ÍÊÇ˵£¬µ±ÎÒÃÇÔÚÏß³Ì1Ö´ÐÐgetter·½·¨µÄʱºò£¨´´½¨µ÷ÓÃÕ»£¬·µ»ØµØÖ·£¬³öÕ»£©£¬Ïß³ÌBÈç¹ûÏëÖ´ÐÐsetter·½·¨£¬±ØÐëÏȵÈgetter·½·¨Íê³É²ÅÄÜÖ´ÐС£¾Ù¸öÀý×Ó£¬ÔÚ32λϵͳÀÈç¹ûͨ¹ýgetter·µ»Ø64λµÄdouble£¬µØÖ·×ÜÏß¿í¶ÈΪ32룬´ÓÄÚ´æµ±ÖжÁÈ¡doubleµÄʱºòÎÞ·¨Í¨¹ýÔ×Ó²Ù×÷Íê³É£¬Èç¹û²»Í¨¹ýatomic¼ÓËø£¬ÓпÉÄÜ»áÔÚ¶ÁÈ¡µÄÖÐ;ÔÚÆäËûÏ̷߳¢Éúsetter²Ù×÷£¬´Ó¶ø³öÏÖÒì³£Öµ¡£Èç¹û³öÏÖÕâÖÖÒì³£Öµ£¬¾Í·¢ÉúÁ˶àÏ̲߳»°²È«¡£
Óô¦¶þ£ºÉèÖÃMemory Barrier
¶ÔÓÚObjective CµÄʵÏÖÀ´Ëµ£¬¼¸ºõËùÓеļÓËø²Ù×÷×îºó¶¼»áÉèÖÃmemory barrier£¬atomic±¾ÖÊÉÏÊǶÔgetter£¬setter¼ÓÁËËø£¬ËùÒÔÒ²»áÉèÖÃmemory
barrier¡£¹Ù·½Îĵµ±íÊöÈçÏ£º
Note: Most types of locks also incorporate a memory barrier to ensure that any preceding load and store instructions are completed before entering the critical section. |
memory barrierÓÐʲôÓô¦ÄØ£¿
memory barrierÄܹ»±£Ö¤ÄÚ´æ²Ù×÷µÄ˳Ðò£¬°´ÕÕÎÒÃÇ´úÂëµÄÊéд˳ÐòÀ´¡£ÌýÆðÀ´Óе㲻¿É˼Ò飬ÊÂʵÊDZàÒëÆ÷»á¶ÔÎÒÃǵĴúÂë×öÓÅ»¯£¬ÔÚËüÈÏΪºÏÀíµÄ³¡¾°¸Ä±äÎÒÃÇ´úÂë×îÖÕ·Òë³ÉµÄ»úÆ÷Ö¸Áî˳Ðò¡£Ò²¾ÍÊÇ˵ÈçÏ´úÂ룺
self.intA = 0; //line 1 self.intB = 1; //line 2 |
±àÒëÆ÷¿ÉÄÜÔÚһЩ³¡¾°ÏÂÏÈÖ´ÐÐline2£¬ÔÙÖ´ÐÐline1£¬ÒòΪËüÈÏΪAºÍBÖ®¼ä²¢²»´æÔÚÒÀÀµ¹ØÏµ£¬ËäÈ»ÔÚ´úÂëÖ´ÐеÄʱºò£¬ÔÚÁíÒ»¸öÏß³ÌintAºÍintB´æÔÚijÖÖÒÀÀµ£¬±ØÐëÒªÇóline1ÏÈÓÚline2Ö´ÐС£
Èç¹ûÉèÖÃpropertyΪatomic£¬Ò²¾ÍÊÇÉèÖÃÁËmemory barrierÖ®ºó£¬¾ÍÄܹ»±£Ö¤line1µÄÖ´ÐÐÒ»¶¨ÊÇÏÈÓÚline2µÄ£¬µ±È»ÕâÖÖ³¡¾°·Ç³£º±¼û£¬Ò»ÔòÊdzöÏÖ±äÁ¿¿çÏ̷߳ÃÎÊÒÀÀµ£¬¶þÊÇÓöÉϱàÒëÆ÷µÄÓÅ»¯£¬Á½¸öÌõ¼þȱһ²»¿É¡£ÕâÖÖ¼«¶ËµÄ³¡¾°Ï£¬atomicȷʵ¿ÉÒÔÈÃÎÒÃǵĴúÂë¸ü¼Ó¶àḬ̈߳²È«Ò»µã£¬µ«ÎÒдiOS´úÂëÖÁ½ñ£¬»¹Î´Óöµ½¹ýÕâÖÖ³¡¾°£¬½Ï´óµÄ¿ÉÄÜÐÔÊDZàÒëÆ÷ÒѾ×ã¹»´ÏÃ÷£¬ÔÚÎÒÃÇÐèÒªµÄµØ·½ÉèÖÃmemory
barrierÁË¡£
ÊDz»ÊÇʹÓÃÁËatomic¾ÍÒ»¶¨¶àḬ̈߳²È«ÄØ£¿ÎÒÃÇ¿ÉÒÔ¿´¿´ÈçÏ´úÂ룺
@property (atomic, assign) int intA;
//thread A
for (int i = 0; i < 10000; i ++) {
self.intA = self.intA + 1;
NSLog(@"Thread A: %d\n", self.intA);
}
//thread B
for (int i = 0; i < 10000; i ++) {
self.intA = self.intA + 1;
NSLog(@"Thread B: %d\n", self.intA);
} |
¼´Ê¹ÎÒ½«intAÉùÃ÷Ϊatomic£¬×îºóµÄ½á¹ûÒ²²»Ò»¶¨»áÊÇ20000¡£ÔÒò¾ÍÊÇÒòΪself.intA =
self.intA + 1;²»ÊÇÔ×Ó²Ù×÷£¬ËäÈ»intAµÄgetterºÍsetterÊÇÔ×Ó²Ù×÷£¬µ«µ±ÎÒÃÇʹÓÃintAµÄʱºò£¬Õû¸öÓï¾ä²¢²»ÊÇÔ×ӵģ¬ÕâÐи³ÖµµÄ´úÂëÖÁÉÙ°üº¬¶ÁÈ¡(load)£¬+1(add)£¬¸³Öµ(store)Èý²½²Ù×÷£¬µ±Ç°Ïß³ÌstoreµÄʱºò¿ÉÄÜÆäËûÏß³ÌÒѾִÐÐÁËÈô¸É´ÎstoreÁË£¬µ¼ÖÂ×îºóµÄֵСÓÚÔ¤ÆÚÖµ¡£ÕâÖÖ³¡¾°ÎÒÃÇÒ²¿ÉÒÔ³ÆÖ®Îª¶àÏ̲߳»°²È«¡£
Ö¸ÕëProperty
Ö¸ÕëPropertyÒ»°ãÖ¸ÏòÒ»¸ö¶ÔÏ󣬱ÈÈ磺
@property (atomic, strong) NSString* userName; |
ÎÞÂÛiOSϵͳÊÇ32λϵͳ»¹ÊÇ64룬һ¸öÖ¸ÕëµÄÖµ¶¼ÄÜͨ¹ýÒ»¸öÖ¸ÁîÍê³Éload»òÕßstore¡£µ«ºÍprimitive
type²»Í¬µÄÊÇ£¬¶ÔÏóÀàÐÍ»¹ÓÐÄÚ´æ¹ÜÀíµÄÏà¹Ø²Ù×÷¡£ÔÚMRCʱ´ú£¬ÏµÍ³Ä¬ÈÏÉú³ÉµÄsetterÀàËÆÈçÏ£º
- (void)setUserName:(NSString *)userName { if(_uesrName != userName) { [userName retain]; [_userName release]; _userName = userName; } } |
²»½ö½öÊǸ³Öµ²Ù×÷£¬»¹»áÓÐretain£¬releaseµ÷Óá£Èç¹ûpropertyΪnonatomic£¬ÉÏÊöµÄsetter·½·¨¾Í²»ÊÇÔ×Ó²Ù×÷£¬ÎÒÃÇ¿ÉÒÔ¼ÙÉèÒ»ÖÖ³¡¾°£¬Ïß³Ì1ÏÈͨ¹ýgetter»ñÈ¡µ±Ç°_userName£¬Ö®ºóÏß³Ì2ͨ¹ýsetterµ÷ÓÃ[_userName
release];£¬Ïß³Ì1Ëù³ÖÓеÄ_userName¾Í±ä³ÉÎÞЧµÄµØÖ·¿Õ¼äÁË£¬Èç¹ûÔÙ¸øÕâ¸öµØÖ·¿Õ¼ä·¢ÏûÏ¢¾Í»áµ¼ÖÂcrash£¬³öÏÖ¶àÏ̲߳»°²È«µÄ³¡¾°¡£
µ½ÁËARCʱ´ú£¬XcodeÒÑ¾ÌæÎÒÃÇ´¦ÀíÁËretainºÍrelease£¬¾ø´ó²¿·ÖʱºòÎÒÃǶ¼²»ÐèҪȥ¹ØÐÄÄÚ´æµÄ¹ÜÀí£¬µ«retain£¬releaseÆäʵ»¹ÊÇ´æÔÚÓÚ×îºóÔËÐеĴúÂëµ±ÖУ¬atomicºÍnonatomic¶ÔÓÚ¶ÔÏóÀàµÄpropertyÉùÃ÷ÀíÂÛÉÏ»¹ÊÇ´æÔÚ²îÒ죬²»¹ýÎÒÔÚʵ¼ÊʹÓõ±ÖУ¬½«NSString*ÉèÖÃΪnonatomicÒ²´ÓδÓöµ½¹ýÉÏÊö¶àÏ̲߳»°²È«µÄ³¡¾°£¬¼«ÓпÉÄÜARCÔÚÄÚ´æ¹ÜÀíÉϵÄÓÅ»¯ÒѾ½«ÉÏÊö³¡¾°´¦Àí¹ýÁË£¬ËùÒÔÎÒ¸öÈ˾õµÃ£¬Èç¹ûÖ»ÊǶԶÔÏóÀàproperty×öread£¬write£¬atomicºÍnonatomicÔÚ¶àḬ̈߳²È«Éϲ¢Ã»ÓÐʵ¼Ê²î±ð¡£
Ö¸ÕëPropertyÖ¸ÏòµÄÄÚ´æÇøÓò
ÕâÒ»Àà¶àÏ̵߳ķÃÎʳ¡¾°ÊÇÎÒÃǺÜÈÝÒ׳ö´íµÄµØ·½£¬¼´Ê¹ÎÒÃÇÉùÃ÷propertyΪatomic£¬ÒÀÈ»»á³ö´í¡£ÒòΪÎÒÃÇ·ÃÎʵIJ»ÊÇpropertyµÄÖ¸ÕëÇøÓò£¬¶øÊÇpropertyËùÖ¸ÏòµÄÄÚ´æÇøÓò¡£¿ÉÒÔ¿´ÈçÏ´úÂ룺
@property (atomic, strong) NSString* stringA;
//thread A
for (int i = 0; i < 100000; i ++) {
if (i % 2 == 0) {
self.stringA = @"a very long string";
}
else {
self.stringA = @"string";
}
NSLog(@"Thread A: %@\n", self.stringA);
}
//thread B
for (int i = 0; i < 100000; i ++) {
if (self.stringA.length >= 10) {
NSString* subStr = [self.stringA substringWithRange:NSMakeRange(0,
10)];
}
NSLog(@"Thread B: %@\n", self.stringA);
} |
ËäÈ»stringAÊÇatomicµÄproperty£¬¶øÇÒÔÚÈ¡substringµÄʱºò×öÁËlengthÅжϣ¬Ïß³ÌB»¹ÊǺÜÈÝÒ×crash£¬ÒòΪÔÚǰһ¿Ì¶ÁlengthµÄʱºòself.stringA
= @"a very long string";£¬ÏÂÒ»¿ÌÈ¡substringµÄʱºòÏß³ÌAÒѾ½«self.stringA
= @"string";£¬Á¢¼´³öÏÖout of boundsµÄException£¬crash£¬¶àÏ̲߳»°²È«¡£
ͬÑùµÄ³¡¾°»¹´æÔÚ¶Ô¼¯ºÏÀà²Ù×÷µÄʱºò£¬±ÈÈ磺
@property (atomic, strong) NSArray* arr;
//thread A
for (int i = 0; i < 100000; i ++) {
if (i % 2 == 0) {
self.arr = @[@"1", @"2", @"3"];
}
else {
self.arr = @[@"1"];
}
NSLog(@"Thread A: %@\n", self.arr);
}
//thread B
for (int i = 0; i < 100000; i ++) {
if (self.arr.count >= 2) {
NSString* str = [self.arr objectAtIndex:1];
}
NSLog(@"Thread B: %@\n", self.arr);
} |
ͬÀí£¬¼´Ê¹ÎÒÃÇÔÚ·ÃÎÊobjectAtIndex֮ǰ×öÁËcountµÄÅжϣ¬Ïß³ÌBÒÀ¾ÉºÜÈÝÒ×crash£¬ÔÒòÒ²ÊÇÓÉÓÚǰºóÁ½ÐдúÂëÖ®¼äarrËùÖ¸ÏòµÄÄÚ´æÇøÓò±»ÆäËûÏß³ÌÐÞ¸ÄÁË¡£
ËùÒÔÄã¿´£¬ÕæÕýÐèÒª²ÙÐĵÄÊÇÕâÒ»ÀàÄÚ´æÇøÓòµÄ·ÃÎÊ£¬¼´Ê¹ÉùÃ÷ΪatomicҲûÓÐÓã¬ÎÒÃÇÆ½³£App³öÏÖĪÃûÆäÃîÄÑÒÔÖØÏֵĶàÏß³Ìcrash¶àÊÇÊôÓÚÕâÒ»À࣬һµ©ÔÚ¶àÏ̵߳ij¡¾°Ï·ÃÎÊÕâÀàÄÚ´æÇøÓòµÄʱºò£¬ÒªÌáÆðÊ®¶þ·ÖµÄСÐÄ¡£ÈçºÎ±ÜÃâÕâÀàcrashºóÃæ»á̸µ½¡£
Property¶àḬ̈߳²È«Ð¡½á£º
¼ò¶øÑÔÖ®£¬atomicµÄ×÷ÓÃÖ»ÊǸøgetterºÍsetter¼ÓÁ˸öËø£¬atomicÖ»Äܱ£Ö¤´úÂë½øÈëgetter»òÕßsetterº¯ÊýÄÚ²¿Ê±Êǰ²È«µÄ£¬Ò»µ©³öÁËgetterºÍsetter£¬¶àḬ̈߳²È«Ö»ÄÜ¿¿³ÌÐòÔ±×Ô¼º±£ÕÏÁË¡£ËùÒÔatomicÊôÐÔºÍʹÓÃpropertyµÄ¶àḬ̈߳²È«²¢Ã»Ê²Ã´Ö±½ÓµÄÁªÏµ¡£ÁíÍ⣬atomicÓÉÓÚ¼ÓËøÒ²»á´øÀ´Ò»Ð©ÐÔÄÜËðºÄ£¬ËùÒÔÎÒÃÇÔÚ±àдiOS´úÂëµÄʱºò£¬Ò»°ãÉùÃ÷propertyΪnonatomic£¬ÔÚÐèÒª×ö¶àḬ̈߳²È«µÄ³¡¾°£¬×Ô¼ºÈ¥¶îÍâ¼ÓËø×öͬ²½¡£
ÈçºÎ×öµ½¶àḬ̈߳²È«£¿
ÌÖÂÛµ½ÕâÀÆäʵÔõô×öµ½¶àḬ̈߳²È«Ò²±È½ÏÃ÷ÀÊÁË£¬¹Ø¼ü×ÖÊÇatomicity£¨Ô×ÓÐÔ£©£¬Ö»Òª×öµ½Ô×ÓÐÔ£¬Ð¡µ½Ò»¸öprimitive
type±äÁ¿µÄ·ÃÎÊ£¬´óµ½Ò»³¤¶Î´úÂëÂß¼µÄÖ´ÐУ¬Ô×ÓÐÔÄܱ£Ö¤´úÂë´®ÐеÄÖ´ÐУ¬Äܱ£Ö¤´úÂëÖ´Ðе½Ò»°ëµÄʱºò£¬²»»áÓÐÁíÒ»¸öÏ߳̽éÈë¡£
Ô×ÓÐÔÊǸöÏà¶ÔµÄ¸ÅÄËüËùÕë¶ÔµÄ¶ÔÏó£¬Á£¶È¿É´ó¿ÉС¡£
±ÈÈç϶δúÂ룺
if (self.stringA.length >= 10) { NSString* subStr = [self.stringA substringWithRange:NSMakeRange(0, 10)]; } |
ÊÇ·ÇÔ×ÓÐԵġ£
µ«¼ÓËøÒÔºó£º
//thread A [_lock lock]; for (int i = 0; i < 100000; i ++) { if (i % 2 == 0) { self.stringA = @"a very long string"; } else { self.stringA = @"string"; } NSLog(@"Thread A: %@\n", self.stringA); } [_lock unlock];
//thread B
[_lock lock];
if (self.stringA.length >= 10) {
NSString* subStr = [self.stringA substringWithRange:NSMakeRange(0,
10)];
}
[_lock unlock]; |
Õû¶Î´úÂë¾Í¾ßÓÐÔ×ÓÐÔÁË£¬¾Í¿ÉÒÔÈÏΪÊǶàḬ̈߳²È«ÁË¡£
ÔÙ±ÈÈ磺
if (self.arr.count >= 2) { NSString* str = [self.arr objectAtIndex:1]; } |
ÊÇ·ÇÔ×ÓÐԵġ£
¶ø
//thread A [_lock lock]; for (int i = 0; i < 100000; i ++) { if (i % 2 == 0) { self.arr = @[@"1", @"2", @"3"]; } else { self.arr = @[@"1"]; } NSLog(@"Thread A: %@\n", self.arr); } [_lock unlock];
//thread B
[_lock lock];
if (self.arr.count >= 2) {
NSString* str = [self.arr objectAtIndex:1];
}
[_lock unlock]; |
ÊǾßÓÐÔ×ÓÐԵġ£×¢Ò⣬¶ÁºÍд¶¼ÐèÒª¼ÓËø¡£
ÕâÒ²ÊÇΪʲôÎÒÃÇÔÚ×ö¶àḬ̈߳²È«µÄʱºò£¬²¢²»ÊÇͨ¹ý¸øproperty¼Óatomic¹Ø¼ü×ÖÀ´±£Õϰ²È«£¬¶øÊǽ«propertyÉùÃ÷Ϊnonatomic£¨nonatomicûÓÐgetter£¬setterµÄËø¿ªÏú£©£¬È»ºó×Ô¼º¼ÓËø¡£
ÈçºÎʹÓÃÄÄÖÖËø£¿
iOS¸ø´úÂë¼ÓËøµÄ·½Ê½ÓкܶàÖÖ£¬³£ÓõÄÓУº
@synchronized(token)
NSLock
dispatch_semaphore_t
OSSpinLock
Õ⼸ÖÖËø¶¼¿ÉÒÔ´øÀ´Ô×ÓÐÔ£¬ÐÔÄܵÄËðºÄ´ÓÉÏÖÁÏÂÒÀ´Î¸üС¡£
ÎÒ¸öÈ˽¨ÒéÊÇ£¬ÔÚ±àдӦÓòã´úÂëµÄʱºò£¬³ýÁËOSSpinLockÖ®Í⣬Äĸö˳ÊÖÓÃÄĸö¡£Ïà½ÏÓÚÕ⼸¸öËøµÄÐÔÄܲîÒ죬´úÂëÂß¼µÄÕýÈ·ÐÔ¸üÎªÖØÒª¡£¶øÇÒÕ⼸ÕßÖ®¼äµÄÐÔÄܲîÒì¶ÔÓû§À´Ëµ£¬¾ø´ó²¿·Öʱºò¶¼¸ÐÖª²»µ½¡£
µ±È»ÎÒÃÇÒ²»áÓöµ½ÉÙÊý³¡¾°ÐèҪ׷Çó´úÂëµÄÐÔÄÜ£¬±ÈÈç±àдframework£¬»òÕßÔÚ¶àÏ̶߳Áд¹²ÏíÊý¾ÝƵ·±µÄ³¡¾°£¬ÎÒÃÇÐèÒª´óÖÂÁ˽âËø´øÀ´µÄËðºÄµ½µ×ÓжàÉÙ¡£
¹Ù·½ÎĵµÓиöÊý¾Ý£¬Ê¹ÓÃIntel-based iMac with a 2 GHz Core Duo processor
and 1 GB of RAM running OS X v10.5²âÊÔ£¬»ñÈ¡mutexÓдó¸Å0.2msµÄËðºÄ£¬ÎÒÃÇ¿ÉÒÔÈÏÎªËø´øÀ´µÄËðºÄ´óÖÂÔÚms¼¶±ð¡£
Atomic Operations
Æäʵ³ýÁ˸÷ÖÖËøÖ®Í⣬iOSÉÏ»¹ÓÐÁíÒ»ÖÖ°ì·¨À´»ñÈ¡Ô×ÓÐÔ£¬Ê¹ÓÃAtomic
Operations£¬Ïà±ÈËøµÄËðºÄҪСһ¸öÊýÁ¿¼¶×óÓÒ£¬ÔÚһЩ׷Çó¸ßÐÔÄܵĵÚÈý·½Framework´úÂëÀï¿ÉÒÔ¿´µ½ÕâЩAtomic
OperationsµÄʹÓá£ÕâЩatomic operation¿ÉÒÔÔÚ/usr/include/libkern/OSAtomic.hÖв鵽£º

±ÈÈç
ÊÇ·ÇÔ×ÓÐԵġ£
¶ø
OSAtomicIncrement32(&(_intA)); |
ÊÇÔ×ÓÐԵ쬶àḬ̈߳²È«µÄ¡£
Atomic OperationÖ»ÄÜÓ¦ÓÃÓÚ32λ»òÕß64λµÄÊý¾ÝÀàÐÍ£¬ÔÚ¶àÏß³ÌʹÓÃNSString»òÕßNSArrayÕâÀà¶ÔÏóµÄ³¡¾°£¬»¹ÊǵÃʹÓÃËø¡£
´ó²¿·ÖµÄAtomic Operation¶¼ÓÐOSAtomicXXX£¬OSAtomicXXXBarrierÁ½¸ö°æ±¾£¬Barrier¾ÍÊÇÇ°ÃæÌáµ½µÄmemory
barrier£¬ÔÚ¶àÏ̶߳à¸ö±äÁ¿Ö®¼ä´æÔÚÒÀÀµµÄʱºòʹÓÃBarrierµÄ°æ±¾£¬Äܹ»±£Ö¤ÕýÈ·µÄÒÀÀµË³Ðò¡£
¶ÔÓÚÆ½Ê±±àдӦÓòã¶àḬ̈߳²È«´úÂ룬ÎÒ»¹Êǽ¨Òé´ó¼Ò¶àʹÓÃ@synchronized£¬NSLock£¬»òÕßdispatch_semaphore_t£¬¶àḬ̈߳²È«±È¶àÏß³ÌÐÔÄܸüÖØÒª£¬Ó¦¸ÃÔÚǰÕߵõ½³ä·Ö±£Ö¤£¬ÓÌÓÐÓàÁ¦µÄʱºòÔÙÈ¥×·ÇóºóÕß¡£
¾¡Á¿±ÜÃâ¶àÏ̵߳ÄÉè¼Æ
ÎÞÂÛÎÒÃÇд¹ý¶àÉÙ´úÂ룬¶¼±ØÐëÒª³ÐÈ϶àḬ̈߳²È«ÊǸö¸´ÔÓµÄÎÊÌ⣬×÷Ϊ³ÌÐòÔ±ÎÒÃÇÓ¦¸Ã¾¡¿ÉÄܵıÜÃâ¶àÏ̵߳ÄÉè¼Æ£¬¶ø²»ÊÇÈ¥×·Çó¸ßÃ÷µÄʹÓÃËøµÄ¼¼ÄÜ¡£
ºóÃæÎÒ»áдһƪÎÄÕ£¬½éÉܺ¯Êýʽ±à³Ì¼°ÆäºËÐÄ˼Ï룬¼´Ê¹ÎÒÃÇʹÓ÷Ǻ¯ÊýʽµÄ±à³ÌÓïÑÔ£¬±ÈÈçObjective
C£¬Ò²Äܼ«´óµÄ°ïÖúÎÒÃDZÜÃâ¶àḬ̈߳²È«µÄÎÊÌâ¡£
×ܽá
iOS϶àÏ̲߳»°²È«µÄ·ÖÎöÖÁ´Ë½áÊøÁË£¬ÈçºÎ±àд¶àḬ̈߳²È«µÄ´úÂ룬˵µ½µ×»¹ÊÇÔÚÓÚ¶Ômemory layoutºÍÔ×ÓÐÔµÄÀí½â£¬Ò²Ï£ÍûÕâÆªÎÄÕ½«atomicºÍnonatomicµÄÕæÕýÇø±ð½âÊÍÇå³þÁË:)¡£ |