- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道使用 dispatch_barrier_async
来锁定给定的资源,但在我的例子中它不是一个好的候选者,因为我不是在修改共享数据结构,而是修改磁盘上的资源并且不不想阻塞整个队列,而只是阻塞一个给定的键,因为操作可能需要很长时间。我不确定文件系统如何从多个线程同时访问同一个文件(按名称),并且在文档中找不到明确的答案,只是最佳实践。我想我想按“文件名”锁定 - 并且缺少方法“tryLock(key)
”
类似于:
-(void)readFileAtPath:(NSString *)path completion:(void(^)(NSData *fileData))completion
{
dispatch_async(self.concurrentQueue,^{
// acquire the lock for a given key and block until can acquire
trylock(path);
NSData *fileData = [self dataAtPath:path];
unlock(path);
completion(fileData);
});
}
-(void)writeData:(NSData *)data toPath:(NSString *)path completion:(void(^)())completion
{
dispatch_async(self.concurrentQueue,^{
// if someone is reading the data at 'path' then this should wait - otherwise should write
trylock(path);
[data writeToFile:path atomically:YES];
unlock(path);
completion();
});
}
编辑:
@synchronized
会这样做吗?这是一个合适的用例吗?
最佳答案
如果你想创建“作用域队列”,就去做吧。为每个文件创建一个串行队列,并让它们以您的并发队列为目标。它可能看起来像这样:
@interface Foo : NSObject
@property (readonly) dispatch_queue_t concurrentQueue;
@end
@implementation Foo
{
NSMutableDictionary* _fileQueues;
dispatch_queue_t _dictGuard;
}
@synthesize concurrentQueue = _concurrentQueue;
- (instancetype)init
{
if (self = [super init])
{
_concurrentQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
_dictGuard = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
_fileQueues = [[NSMutableDictionary alloc] init];
}
return self;
}
- (dispatch_queue_t)queueForFile: (NSString*)path
{
__block dispatch_queue_t retVal = NULL;
dispatch_sync(_dictGuard, ^{
retVal = _fileQueues[path];
if (!retVal)
{
retVal = dispatch_queue_create(path.UTF8String, DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(retVal, self.concurrentQueue);
_fileQueues[path] = retVal;
}
});
return retVal;
}
- (void)doStuff: (id)stuff withFile: (NSString*)path
{
dispatch_queue_t fileQueue = [self queueForFile: path];
dispatch_async(fileQueue, ^{
DoStuff(stuff, path);
});
}
@end
就是说,这个每个文件队列的东西有一点“代码味道”,特别是如果它旨在提高 I/O 性能。就在我的脑海中,为了获得最佳性能,感觉每个物理设备都有一个队列比每个文件有一个队列更好。通常情况下,您作为开发人员并不比操作系统/系统框架更了解如何协调文件系统访问,因此您肯定希望在之前和之后进行衡量,以确保这种方法确实提高了您的性能。当然,有时您会知道一些操作系统不知道的事情,但您可能想寻找一种方法为操作系统提供该信息,而不是重新发明轮子。在读写性能方面,如果您使用 dispatch_io
channel 来读取和写入文件,您将向 GCD 提供最佳协调文件访问所需的信息。
我还想到您可能也在尝试“保护应用程序不受其自身影响”。就像,如果您将磁盘用作缓存,其中多个任务可能同时访问该文件,您可能需要保护一个读取器免受另一个写入器的影响。如果是这种情况,您可能希望寻找一些现有的框架来解决需求,而不是自行开发。此外,在此用例中,您可能需要考虑在应用程序内管理您的范围,而只是 mmap
一个大文件,但这种方法的成本/ yield 将取决于文件的粒度。
如果没有关于应用程序的更多上下文,很难说更多。
对于您的后续问题:@synchronized
可以用于实现此目的,但并非没有与上面发布的 GCD 方式相同的机制。原因是@synchronized(foo)
在 foo
上同步通过身份(指针相等)而不是值相等(即-isEqual:
),所以NSString
和 NSURL
(用于引用文件的两个最明显的对象)具有值语义,使它们成为不佳的候选对象。使用 @synchronized
的实现可能看起来像这样:
@interface Bar : NSObject
@property (readonly) dispatch_queue_t concurrentQueue;
@end
@implementation Bar
{
NSMutableDictionary* _lockObjects;
dispatch_queue_t _dictGuard;
}
- (instancetype)init
{
if (self = [super init])
{
_concurrentQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
_dictGuard = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
_lockObjects = [[NSMutableDictionary alloc] init];
}
return self;
}
@synthesize concurrentQueue = _concurrentQueue;
- (id)lockForFile: (NSString*)path
{
__block id retVal = NULL;
dispatch_sync(_dictGuard, ^{
retVal = _lockObjects[path];
if (!retVal)
{
retVal = [[NSObject alloc] init];
_lockObjects[path] = retVal;
}
});
return retVal;
}
- (void)syncDoStuff: (id)stuff withFile: (NSString*)path
{
id fileLock = [self lockForFile: path];
@synchronized(fileLock)
{
DoStuff(stuff, path);
}
}
- (void)asyncDoStuff: (id)stuff withFile: (NSString*)path
{
id fileLock = [self lockForFile: path];
dispatch_async(self.concurrentQueue, ^{
@synchronized(fileLock)
{
DoStuff(stuff, path);
}
});
}
@end
您会看到我创建了两种方法来做事,一种是同步的,另一种是异步的。 @synchronized
提供互斥机制,但不是异步调度机制,所以如果你想要并行,你仍然必须从 GCD(或其他东西)获得它。总而言之,虽然你可以 使用 @synchronized
要做到这一点,现在这不是一个好的选择。它明显比等效的 GCD 机制慢。关于唯一一次@synchronized
现在有用的是作为实现递归锁定的语法快捷方式。也就是说,许多聪明人认为递归锁定是一种反模式。 (有关原因的更多详细信息,请查看 this link。)它的长短是 @synchronized
。不是解决这个问题的最佳方法。
关于ios 基于 key 创建写锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25400809/
一、公平锁和非公平锁 1.1、公平锁和非公平锁的概述 公平锁:指多个线程按照申请锁的顺序来获取锁。 非公平锁:指在多线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取到锁
阅读目录 1、简介 2、分类 3、全局锁 4、表级锁 5、表锁 6、元数据锁
因此,在我编写的程序中,我有三个函数,为了简单起见,我们将它们称为 A、B 和 C。每个函数都需要访问资源X才能工作。 限制是A和B不允许同时运行并且必须适当同步。但是,C 可以与 A 或 B 同时运
我听说过这些与并发编程相关的词,但是锁、互斥量和信号量之间有什么区别? 最佳答案 锁只允许一个线程进入被锁定的部分,并且该锁不与任何其他进程共享。 互斥锁与锁相同,但它可以是系统范围的(由多个进程共享
这个问题已经有答案了: What is an efficient way to implement a singleton pattern in Java? [closed] (29 个回答) 已关闭
这个问题已经有答案了: What is an efficient way to implement a singleton pattern in Java? [closed] (29 个回答) 已关闭
我对标题中的主题有几个问题。首先,假设我们使用 JDBC,并且有 2 个事务 T1 和 T2。在 T1 中,我们在一个特定的行上执行 select 语句。然后我们对该行执行更新。在事务 T2 中,我们
我希望我的函数只运行一次。这意味着如果多个线程同时调用它,该函数将阻塞所有线程,只允许它运行。 最佳答案 听起来您希望存储过程进行同步。为什么不直接将同步放在应用程序本身中。 pthread_mute
if (runInDemoMode) { lock (this) { //Initalization of tables dCreator.create
我相信无论使用什么语言都可以考虑我的问题,但是为了有一些“ anchor ”,我将使用 Java 语言来描述它。 让我们考虑以下场景:我有一个扩展 Thread 的类 PickyHost 及其实例 p
我知道异步不是并行的,但我现在遇到了一个非常有趣的情况。 async function magic(){ /* some processing here */ await async () =
我们正在使用 Scala、Play 框架和 MongoDB(以 ReactiveMongo 作为我们的驱动程序)构建一个网络应用程序。应用程序架构是端到端的非阻塞。 在我们代码的某些部分,我们需要访问
我需要一个简单的锁,JavaME 超时(concurrent.lock 的反向移植需要完整的 Java 1.3)。 如果其他人已经为 JavaME 发布了经过测试的锁定代码,我宁愿使用它。 锁定是出了
根据 boost : To access the object, a weak_ptr can be converted to a shared_ptr using the shared_ptr co
关于 Mutex 和 Critical 部分之间的区别存在一个问题,但它也不处理 Locks。 所以我想知道临界区是否可以用于进程之间的线程同步。 还有信号状态和非信号状态的含义 最佳答案 在 Win
锁 最为常见的应用就是 高并发的情况下,库存的控制。本次只做简单的单机锁介绍。 直接看代码: 每请求一次库存-1. 假如库存1000,在1000个人请求之后,库存将变为0。
线程和进程 1、线程共享创建它的进程的地址空间,进程有自己的地址空间 2、线程可以访问进程所有的数据,线程可以相互访问 3、线程之间的数据是独立的 4、子进程复制线程的数据 5、子进程启动
**摘要:**细心的你也一定关注到,有的网址是https开头的,有的是http。https开头的网站前面,会有一把小锁。这是为什么呢? 本文分享自华为云社区《还不知道SSL证书已经是刚需了?赶快来了解
试图在 C 中实现一个非常简单的互斥锁(锁)我有点困惑。我知道互斥锁类似于二进制信号量,除了互斥锁还强制执行释放锁的线程的约束,必须是最近获得它的同一线程。我对如何跟踪所有权感到困惑? 这是我到目前为
在阅读了很多与上述主题相关的文章和答案之后,我仍然想知道 SQL Server 数据库引擎在以下示例中是如何工作的: 假设我们有一个名为 t3 的表: create table t3 (a int ,
我是一名优秀的程序员,十分优秀!