我写的类SafeMutableDictionary继承了NSMutableDictionary 类仅实现“原始”方法,must be inherits 来自NSDictionary:
sudo u+x gradlew.sh
来自NSMutableDictionary:
- (instancetype)init;
- (instancetype)initWithObjects:(const id [])objects forKeys:(const id<NSCopying>[])keys count:(NSUInteger)cnt;
- (NSUInteger)count;
- (id)objectForKey:(id)key;
- (NSEnumerator*)keyEnumerator;
线程安全支持使用NSMutableDictionary类型的内部变量,它包含所有数据
- (void)removeObjectForKey:(id)key;
- (void)setObject:(id)obj forKey:(id)key;
并且每次访问使用@interface SafeMutableDictionary () {
__strong NSMutableDictionary* _dictEmbedded;
}
阻止。
@synchronized
使用github中的完整代码回购。
但是,不幸的是,我仍然遇到像
这样的错误- (id)objectForKey:(id)key{
@synchronized (_dictEmbedded) {
return [_dictEmbedded objectForKey:key];
}
}
所以,我有一些问题:
1)我的实施是否正确?我错过了什么?
2)是否存在更为着名且经过测试的解决方案?
3)同时从main和bg线程访问容器的最佳实践是什么?
可能是最糟糕的做法是做这样的继承,并且更好地使用原始容器+关注线程安全
答案 0 :(得分:2)
查看使用已同步Does @synchronized guarantees for thread safety or not?
答案 1 :(得分:1)
这里有两个不同的要求:
多线程安全,即当多个线程同时访问时,集合(或您的字典中的字典)保持一致。
当同时修改集合时,稳健性,即迭代器(有时称为枚举器)保持一致(例如,枚举集合并删除枚举器返回的所选元素)。即使在单线程环境中,这也是一个挑战。
您的解决方案解决了要求1.但您收到的错误消息是关于要求2. NSDictionary
实例不健全。很少有收集要求(使用任何编程语言)。
答案 2 :(得分:0)
@synchronized
向您保证,您无法同时从多个主题访问某个对象,但如果出现这种情况,并不能保证一切正常。
我为解决这个问题所做的是创建一个基类NBSharedObjectWithLock: 有了这个课程,你可以:
myObjetc = [[MyClassInheritingFromNBSharedObjectWithLoc] alloc] initWithMutexMode:PTHREAD_MUTEX_RECURSIVE];
[myObject lock]; // when you need exclusive access to the object
[myObject unlock]; // when exclusive access to the object is no more needed
<强> NBSharedObjectWithLoc.h 强>
//
// NBSharedObjectWithLock.h
// NBFoundation
//
// Created by Nicolas Buquet on 03/06/2016.
// Copyright © 2016 Nicolas Buquet. All rights reserved.
//
#import <Foundation/Foundation.h>
#include <pthread.h>
@interface NBSharedObjectWithLock : NSObject
- (instancetype)initWithMutexMode:(int)mutexMode;
// mutexMode can be:
// - PTHREAD_MUTEX_NORMAL
// - PTHREAD_MUTEX_ERRORCHECK
// - PTHREAD_MUTEX_RECURSIVE
// - PTHREAD_MUTEX_DEFAULT ( = PTHREAD_MUTEX_NORMAL )
- (BOOL)lock;
- (BOOL)unlock;
@end
<强> NBSharedObjectWithLoc.m 强>
//
// NBSharedObjectWithLock.m
// NBFoundation
//
// Created by Nicolas Buquet on 03/06/2016.
// Copyright © 2016 Nicolas Buquet. All rights reserved.
//
#import "NBSharedObjectWithLock.h"
@implementation NBSharedObjectWithLock
{
pthread_mutex_t _mutexLock;
}
- (instancetype)initWithMutexMode:(int)mutexMode
{
// mutexMode can be:
// - PTHREAD_MUTEX_NORMAL
// - PTHREAD_MUTEX_ERRORCHECK
// - PTHREAD_MUTEX_RECURSIVE
// - PTHREAD_MUTEX_DEFAULT ( = PTHREAD_MUTEX_NORMAL )
self = [super init];
if (!self )
return nil;
pthread_mutexattr_t mutexAttributes;
pthread_mutexattr_init(&mutexAttributes);
pthread_mutexattr_settype(&mutexAttributes, mutexMode);
pthread_mutex_init(&_mutexLock, &mutexAttributes);
return self;
}
- (void)dealloc
{
pthread_mutex_destroy(&_mutexLock);
[super dealloc];
}
- (BOOL)lock
{
return pthread_mutex_lock(&_mutexLock);
}
- (BOOL)unlock
{
return pthread_mutex_unlock(&_mutexLock);
}
@end
使用这些基类,可以从一个线程访问对象。将锁上一把锁。如果另一个线程想要访问它,它将等待(线程将被暂停),直到释放对象的锁定。如果锁定在同一个线程上,则同一线程上的多个对象可以访问锁定的对象。
锁定/解锁调用会替换@synchronize块。 请注意,您不能在锁定调用和解锁调用之间返回,否则您的对象将永远不会被解锁。如果您需要返回一个值:
- (NSDictionary *)dictionaryFromLockedObject
{
[myObject lock]
NSDictionary *dict = [myObject callAMethodThatReturnsADictionary];
[myObject unlock]
return dict;
}