Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modifying lock to improve code performance #667

Merged
merged 2 commits into from
Mar 27, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions MJExtension/MJExtensionConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,13 @@

#import <Foundation/Foundation.h>

// 信号量
#define MJExtensionSemaphoreCreate \
static dispatch_semaphore_t signalSemaphore; \
static dispatch_once_t onceTokenSemaphore; \
dispatch_once(&onceTokenSemaphore, ^{ \
signalSemaphore = dispatch_semaphore_create(1); \
});

#define MJExtensionSemaphoreWait \
dispatch_semaphore_wait(signalSemaphore, DISPATCH_TIME_FOREVER);

#define MJExtensionSemaphoreSignal \
dispatch_semaphore_signal(signalSemaphore);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上面删掉的代码在其他类里的改动和放在这里应该是一样的. define 宏定义只是在编译阶段替换而已.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

使用 MJ_LOCK () 主要原因是不使用全局的一把锁,在每个对应的功能点加锁,后期如果还有线程安全相关问题,使用自己定义的锁,提高锁的效率:

MJ_LOCK(self.propertyKeysLock);
self.propertyKeysDict[key] = propertyKeys;
MJ_UNLOCK(self.propertyKeysLock);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

主要目的是不使用全局的那一把锁

#ifndef MJ_LOCK
#define MJ_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER)
#endif

#ifndef MJ_UNLOCK
#define MJ_UNLOCK(lock) dispatch_semaphore_signal(lock)
#endif

// 过期
#define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
Expand Down
29 changes: 18 additions & 11 deletions MJExtension/MJProperty.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
@interface MJProperty()
@property (strong, nonatomic) NSMutableDictionary *propertyKeysDict;
@property (strong, nonatomic) NSMutableDictionary *objectClassInArrayDict;
@property (strong, nonatomic) dispatch_semaphore_t propertyKeysLock;
@property (strong, nonatomic) dispatch_semaphore_t objectClassInArrayLock;
@end

@implementation MJProperty
Expand All @@ -24,22 +26,21 @@ - (instancetype)init
if (self = [super init]) {
_propertyKeysDict = [NSMutableDictionary dictionary];
_objectClassInArrayDict = [NSMutableDictionary dictionary];
_propertyKeysLock = dispatch_semaphore_create(1);
_objectClassInArrayLock = dispatch_semaphore_create(1);
}
return self;
}

#pragma mark - 缓存
+ (instancetype)cachedPropertyWithProperty:(objc_property_t)property
{
MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJProperty *propertyObj = objc_getAssociatedObject(self, property);
if (propertyObj == nil) {
propertyObj = [[self alloc] init];
propertyObj.property = property;
objc_setAssociatedObject(self, property, propertyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
MJExtensionSemaphoreSignal
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MJPropertySemaphoreCreate
MJ_LOCK(_propertySemaphore);
NSArray *cachedProperties = [self properties];
MJ_UNLOCK(_propertySemaphore);

[self properties];方法已加锁,此处并没有其他线程同时进入,所以并不需要加锁

return propertyObj;
}

Expand Down Expand Up @@ -156,17 +157,20 @@ - (void)setPorpertyKeys:(NSArray *)propertyKeys forClass:(Class)c
NSString *key = NSStringFromClass(c);
if (!key) return;

MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJ_LOCK(self.propertyKeysLock);
self.propertyKeysDict[key] = propertyKeys;
MJExtensionSemaphoreSignal
MJ_UNLOCK(self.propertyKeysLock);
}

- (NSArray *)propertyKeysForClass:(Class)c
{
NSString *key = NSStringFromClass(c);
if (!key) return nil;
return self.propertyKeysDict[key];

MJ_LOCK(self.propertyKeysLock);
NSArray *propertyKeys = self.propertyKeysDict[key];
MJ_UNLOCK(self.propertyKeysLock);
return propertyKeys;
}

/** 模型数组中的模型类型 */
Expand All @@ -176,16 +180,19 @@ - (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c
NSString *key = NSStringFromClass(c);
if (!key) return;

MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJ_LOCK(self.objectClassInArrayLock);
self.objectClassInArrayDict[key] = objectClass;
MJExtensionSemaphoreSignal
MJ_UNLOCK(self.objectClassInArrayLock);
}

- (Class)objectClassInArrayForClass:(Class)c
{
NSString *key = NSStringFromClass(c);
if (!key) return nil;
return self.objectClassInArrayDict[key];

MJ_LOCK(self.objectClassInArrayLock);
Class objectClass = self.objectClassInArrayDict[key];
MJ_UNLOCK(self.objectClassInArrayLock);
return objectClass;
}
@end
3 changes: 0 additions & 3 deletions MJExtension/MJPropertyType.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@ + (instancetype)cachedTypeWithCode:(NSString *)code
types = [NSMutableDictionary dictionary];
});

MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJPropertyType *type = types[code];
if (type == nil) {
type = [[self alloc] init];
type.code = code;
types[code] = type;
}
MJExtensionSemaphoreSignal
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上

return type;
}

Expand Down
22 changes: 13 additions & 9 deletions MJExtension/NSObject+MJClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
#import "MJFoundation.h"
#import <objc/runtime.h>

#define MJClassSemaphoreCreate \
static dispatch_semaphore_t _classSemaphore; \
static dispatch_once_t onceTokenSemaphore; \
dispatch_once(&onceTokenSemaphore, ^{ \
_classSemaphore = dispatch_semaphore_create(1); \
});

static const char MJAllowedPropertyNamesKey = '\0';
static const char MJIgnoredPropertyNamesKey = '\0';
static const char MJAllowedCodingPropertyNamesKey = '\0';
Expand Down Expand Up @@ -139,17 +146,16 @@ + (void)mj_setupBlockReturnValue:(id (^)(void))block key:(const char *)key
}

// 清空数据
MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJClassSemaphoreCreate
MJ_LOCK(_classSemaphore);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MJClassSemaphoreCreate 这里的宏, 并没有指出真正的变量内容
MJ_LOCK(_classSemaphore); 这里使用的 _classSemaphore 太隐含了.

[[self classDictForKey:key] removeAllObjects];
MJExtensionSemaphoreSignal
MJ_UNLOCK(_classSemaphore);
}

+ (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)key
{
MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait

MJClassSemaphoreCreate
MJ_LOCK(_classSemaphore);
NSMutableArray *array = [self classDictForKey:key][NSStringFromClass(self)];
if (array == nil) {
// 创建、存储
Expand All @@ -170,9 +176,7 @@ + (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)
[array addObjectsFromArray:subArray];
}];
}

MJExtensionSemaphoreSignal

MJ_UNLOCK(_classSemaphore);
return array;
}
@end
31 changes: 19 additions & 12 deletions MJExtension/NSObject+MJProperty.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
#pragma clang diagnostic ignored "-Wundeclared-selector"
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

#define MJPropertySemaphoreCreate \
static dispatch_semaphore_t _propertySemaphore; \
static dispatch_once_t onceTokenSemaphore; \
dispatch_once(&onceTokenSemaphore, ^{ \
_propertySemaphore = dispatch_semaphore_create(1); \
});

static const char MJReplacedKeyFromPropertyNameKey = '\0';
static const char MJReplacedKeyFromPropertyName121Key = '\0';
static const char MJNewValueFromOldValueKey = '\0';
Expand Down Expand Up @@ -135,10 +142,10 @@ + (Class)propertyObjectClassInArray:(NSString *)propertyName
+ (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration
{
// 获得成员变量
MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJPropertySemaphoreCreate
MJ_LOCK(_propertySemaphore);
NSArray *cachedProperties = [self properties];
MJExtensionSemaphoreSignal
MJ_UNLOCK(_propertySemaphore);
// 遍历成员变量
BOOL stop = NO;
for (MJProperty *property in cachedProperties) {
Expand Down Expand Up @@ -219,31 +226,31 @@ + (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray
{
[self mj_setupBlockReturnValue:objectClassInArray key:&MJObjectClassInArrayKey];

MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJPropertySemaphoreCreate
MJ_LOCK(_propertySemaphore);
[[self propertyDictForKey:&MJCachedPropertiesKey] removeAllObjects];
MJExtensionSemaphoreSignal
MJ_UNLOCK(_propertySemaphore);
}

#pragma mark - key配置
+ (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName
{
[self mj_setupBlockReturnValue:replacedKeyFromPropertyName key:&MJReplacedKeyFromPropertyNameKey];

MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJPropertySemaphoreCreate
MJ_LOCK(_propertySemaphore);
[[self propertyDictForKey:&MJCachedPropertiesKey] removeAllObjects];
MJExtensionSemaphoreSignal
MJ_UNLOCK(_propertySemaphore);
}

+ (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121
{
objc_setAssociatedObject(self, &MJReplacedKeyFromPropertyName121Key, replacedKeyFromPropertyName121, OBJC_ASSOCIATION_COPY_NONATOMIC);

MJExtensionSemaphoreCreate
MJExtensionSemaphoreWait
MJPropertySemaphoreCreate
MJ_LOCK(_propertySemaphore);
[[self propertyDictForKey:&MJCachedPropertiesKey] removeAllObjects];
MJExtensionSemaphoreSignal
MJ_UNLOCK(_propertySemaphore);
}
@end

Expand Down