- ( void ) viewDidLoad {
[ super viewDidLoad] ;
NSLog ( @"123" ) ;
[ self wm_crash] ;
}
- ( void ) wm_crash{
for ( int i = 0 ; i < 200000 ; i++ ) {
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
_testArray = [ NSMutableArray array] ;
} ) ;
}
}
上篇@synchronize我们已经研究过,现在我们上面的代码加锁!
- ( void ) wm_crash{
for ( int i = 0 ; i < 200000 ; i++ ) {
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
@ synchronized ( _testArray) {
_testArray = [ NSMutableArray array] ;
}
} ) ;
}
}
- ( void ) wm_crash{
for ( int i = 0 ; i < 200000 ; i++ ) {
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
@ synchronized ( self ) {
_testArray = [ NSMutableArray array] ;
}
} ) ;
}
}
这里需要说一下:我们说过,@synchronize当加锁对象为nil时,do nothing不做任何处理,我们对_testArray加锁时,这里_testArray是会为nil的,导致加锁失败!出现异常!!!但是使用self时,self一定部位nil,所以不会出现异常! 但是这里我想说,synchronize的效率比较低,而且此处我们有更优解! NSLock 互斥锁
- ( void ) wm_crash{
NSLock * lock = [ [ NSLock alloc] init] ;
for ( int i = 0 ; i < 200000 ; i++ ) {
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
[ lock lock] ;
_testArray = [ NSMutableArray array] ;
[ lock unlock] ;
} ) ;
}
}
NSLock在Foundation框架,swift的有开源,这里去看一下swift的底层源码!
public override init ( ) {
#if os(Windows)
InitializeSRWLock ( mutex)
InitializeConditionVariable ( timeoutCond)
InitializeSRWLock ( timeoutMutex)
#else
pthread_mutex_init ( mutex, nil)
#if os(macOS) || os(iOS)
pthread_cond_init ( timeoutCond, nil)
pthread_mutex_init ( timeoutMutex, nil)
#endif
#endif
}
public override init ( ) {
super . init ( )
#if os(Windows)
InitializeCriticalSection ( mutex)
InitializeConditionVariable ( timeoutCond)
InitializeSRWLock ( timeoutMutex)
#else
#if CYGWIN
var attrib : pthread_mutexattr_t? = nil
#else
var attrib = pthread_mutexattr_t ( )
#endif
withUnsafeMutablePointer ( to: & attrib) { attrs in
pthread_mutexattr_init ( attrs)
pthread_mutexattr_settype ( attrs, Int32 ( PTHREAD_MUTEX_RECURSIVE) )
pthread_mutex_init ( mutex, attrs)
}
#if os(macOS) || os(iOS)
pthread_cond_init ( timeoutCond, nil)
pthread_mutex_init ( timeoutMutex, nil)
#endif
#endif
}
- ( void ) wm_testRecursive{
NSLock * lock = [ [ NSLock alloc] init] ;
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
static void ( ^ testBlock) ( int ) ;
testBlock = ^ ( int value) {
[ lock lock] ;
if ( value > 0 ) {
NSLog ( @"current value = %d" , value) ;
testBlock ( value - 1 ) ;
}
[ lock unlock] ;
} ;
testBlock ( 100 ) ;
} ) ;
}
- ( void ) wm_testRecursive{
NSRecursiveLock * lock = [ [ NSRecursiveLock alloc] init] ;
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
static void ( ^ testBlock) ( int ) ;
testBlock = ^ ( int value) {
[ lock lock] ;
if ( value > 0 ) {
NSLog ( @"current value = %d" , value) ;
testBlock ( value - 1 ) ;
}
[ lock unlock] ;
} ;
testBlock ( 100 ) ;
} ) ;
}
- ( void ) wm_testRecursive{
NSRecursiveLock * lock = [ [ NSRecursiveLock alloc] init] ;
for ( int i = 0 ; i < 100 ; i++ ) {
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
static void ( ^ testBlock) ( int ) ;
testBlock = ^ ( int value) {
[ lock lock] ;
if ( value > 0 ) {
NSLog ( @"current value = %d" , value) ;
testBlock ( value - 1 ) ;
}
[ lock unlock] ;
} ;
testBlock ( 10 ) ;
} ) ;
}
}
- ( void ) wm_testRecursive{
for ( int i = 0 ; i < 100 ; i++ ) {
dispatch_async ( dispatch_get_global_queue ( 0 , 0 ) , ^ {
static void ( ^ testBlock) ( int ) ;
testBlock = ^ ( int value) {
@ synchronized ( self ) {
if ( value > 0 ) {
NSLog ( @"current value = %d" , value) ;
testBlock ( value - 1 ) ;
}
}
} ;
testBlock ( 10 ) ;
} ) ;
}
}
所以,我们在使用的时候,看情况来定,当我们是普通线程安全,就使用NSLock就可以了,效率高!但是当我们是递归调用时,就要使用NSRecursiveLock递归锁来保证线程安全!再有就是当我们不仅要使用递归调用,还会有循环的外界线程影响时,就要注意死锁的产生!!!