这个 GCD 实现的 getter setter 线程安全并且比 @synchronized 工作得更好吗?对象

2024-01-10

@interface ViewController ()
@property (nonatomic, strong) NSString *someString;
@end

@implementation ViewController

@synthesize someString = _someString;

- (NSString *)someString {
    __block NSString *tmp;
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        tmp = _someString;
    });
    return tmp;
}

- (void)setSomeString:(NSString *)someString {
    __block NSString *tmp;
    dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        tmp = someString;
    });
    _someString = tmp;
}
@end

有人说这比@synchronized因为所有的锁定都是在 GCD 中处理的。


首先,您的设置器根本没有任何意义,并且使用默认并发队列也可能不是您想要的。您的代码可能应该看起来更像:

@interface ViewController ()
@property (nonatomic, copy) NSString *someString;
@end

@implementation ViewController
{
    dispatch_queue_t _stateGuardQueue;
}

- (instancetype)init
{
    if (self = [super init])
    {
        _stateGuardQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
    }
    return self;
}

@synthesize someString = _someString;

- (NSString *)someString {
    __block NSString *tmp;
    dispatch_sync(_stateGuardQueue, ^{
        tmp = _someString;
    });
    return tmp;
}

- (void)setSomeString:(NSString *)someString {
    NSString* tmp = [someString copy];
    dispatch_barrier_async(_stateGuardQueue, ^{
        _someString = tmp;
    });
}

@end

我所做的改变:

  • 让 setter 实际上在关键部分内进行突变
  • 使用私有的、每个实例的并发队列,而不是全局默认的并发队列;将屏障块提交到默认并发队列不会执行您认为的操作。 (参见docs https://developer.apple.com/library/prerelease/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/c/func/dispatch_barrier_sync)
  • Change dispatch_barrier_sync to dispatch_barrier_async同步等待 setter 块返回是没有意义的,因为没有办法在当前线程上获取过时的读取。
  • 将属性更改为具有copy语义,这始终是值语义类型的良好实践(NSString等)这在可能从多个线程同时读取属性的情况下尤其重要。

要知道的是,孤立地看,这种模式并不提供比原子属性更多的“安全性”,因此您应该只使用这些属性(更少的代码等)。至于性能问题,是的,对于这种特殊用途,GCD 肯定会优于@synchronized。其一,它允许并发读取,其中@synchronized将串行化并发读取。如果不进行测试,我预计原子属性的性能会优于两者。也就是说,原子属性以及一般以这种方式保护单个操作是rarely足够的并发策略。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这个 GCD 实现的 getter setter 线程安全并且比 @synchronized 工作得更好吗?对象 的相关文章

  • 在 iPad 上运行时,不会触发 Mobile Safari 中即将发生的选项卡切换的 Pagehide 事件

    众所周知 Mobile Safari 在以下情况下会暂停网页上的 Javascript 执行 您切换到不同的浏览器选项卡 切换到不同的 iOS 应用程序 例如 当您接到来电时 手机应用程序 您可以订阅窗口 页面隐藏 and 页面展示 事件来
  • clang 3.0 + libc++ 中的 std::async 不起作用?

    我刚刚在我的 ubuntu 10 04 上编译并安装了 clang llvm 3 0 并且还从 svn 编译并安装了 libc 由于 libc 中的状态显示线程支持已完成 因此我想尝试 std async 所以我按照安东尼 威廉姆斯 Ant
  • 派生类在 PySide (Qt/PyQt) 中的错误线程中接收信号

    我在让派生类在 PySide 中正确接收信号时遇到问题 我在主 GUI 或命令行应用程序 线程的两个单独线程上使用发送器和接收器 线程是 QThread 对象 发送器和接收器在创建后立即使用 QObject moveToThread 移动到
  • 将 uiview 转换为 .png 图像

    我正在 iphone 上工作 我采用 UIView 的子类 并在绘制矩形方法中进行一些设计 我想将此视图转换为 png 格式 提前致谢 UIGraphicsBeginImageContext myView frame size myView
  • 与在后台运行应用程序的一台设备进行多点连接

    我想使用多点连接框架连接 2 台设备 其中一台设备在后台运行应用程序 就像 Firechat 一样 我无法确认这是否有效 我已将其安装在 iPhone 5S 和 4 上 但是他们只是找不到彼此 但我在某处读过这有效 实现这一目标的最佳方法是
  • ALAssetPropertyDate 返回“错误”日期

    我目前正在开发一个项目 需要读取一些 纬度 经度和日期 EXIF 数据 位置数据似乎是正确的 但我得到的日期似乎是 上次修改日期 日期 CLLocation loc asset valueForProperty ALAssetPropert
  • CGColorRef 导致崩溃

    我的代码发生了崩溃 并且我一直跟踪到在传递 2 个 CGColorRefs 时发生崩溃的行 以下是对象 CGColorRef startColor UIColor colorWithWhite 0 92 alpha 1 0 CGColor
  • TabBarController:以不同方向定向视图

    我无法保持当前的观点方向 在下面的设置中 我能够将第一个视图控制器锁定为纵向 将第二个视图控制器锁定为横向或纵向 但是 当我向选项卡控制器添加第二个导航控制器 rootviewcontroller 时 整个项目中的所有视图都将变为横向和纵向
  • 使用自定义组件:子类 UIView 或 UIViewController?

    我正在研究 UISegmentedControl 的自定义实现 我想创建一个能够接收配置数据并从中获取类似于 UISegmentedControl 的自定义视图的组件 我开始对 UIView 进行子类化 我可以使用以下代码创建自定义 UIS
  • UIFont fontWithName:仅限于每个系列加载 2 个变体

    这个问题与带有自定义字体的 UILabel 显示 错误 自定义字体 https stackoverflow com questions 4622956 uilabel with custom font displays wrong cust
  • 将字符串编码为 HTML 字符串 Swift 3

    如何快速编码字符串以删除所有特殊字符并将其替换为其匹配的 html 编号 假设我有以下字符串 var mystring This is my String That s it 然后用它的html编号替换特殊字符 38 39 gt 62 但我
  • 当Java中set已经是原子的时候,为什么我们还需要compareAndSet呢?

    因为原子意味着线程安全 当 set 本身在java中是原子和线程安全的时候 我们什么时候使用compareAndSet 举例来说 我想以原子方式设置一个变量 以便每个其他线程都可以看到它 但我希望以线程安全的方式设置该变量 我可以简单地将其
  • 从方案加载 url 第一次未处理 - appdelegate 与 viewcontroller

    我的应用程序已成功打开并将参数 从 URL 方案 即 myApp sometextToPrint 设置为AppDelegate类 但每当我想处理它们时 当从该 URL 打开应用程序时 它就会在第一次失败 我在前台检查器中有一个应用程序 它调
  • 如何消除圆形矩形按钮周围的间隙而不删除其周围的边框? [复制]

    这个问题在这里已经有答案了 顺便提一句 这可能看起来像是关于按钮阴影问题的问题的重复 但它们有单调的背景 在我的例子中 背景是一些图像 所以简单的边框不能解决问题 While making app for iPhone Pad I noti
  • 使用 Swift 创建 SKSpriteNode 子类

    我正在尝试创建作为 SKSpriteNode 子类的类 并且我想向其添加其他属性和函数 但在第一步中我遇到了错误 这是我的代码 import SpriteKit class Ball SKSpriteNode init super init
  • iOS 有没有办法通过按钮调整图像大小?

    如下图所示 按钮的图像跨越了按钮边界 有没有办法通过故事板或以编程方式使图像适合按钮的边界 更改按钮Style from Plain to Default 这是一个限制为60 x 60 with a 80 x 80图像与Style Plai
  • SwiftUI 查看所有视图,包括工作表视图

    我需要根据某些条件在所有视图之上显示一个视图 无论顶视图是什么 我正在尝试以下代码 struct TestView
  • UIButton 图像调整大小/缩放以适合

    我有一个非常严重的问题 我不知道如何解决 我正在对 UIButtons 框架进行动画处理 当我对其进行动画处理时 我希望按钮中的图像缩放到与按钮相同的大小 它无需在我的 iPhone 模拟器上执行任何操作即可运行 但是当我在 iPad 模拟
  • 如何在 JSONKit 中 JSON 序列化 NSDate 字典

    我尝试使用 Jsonkit 和 Apple 的 JSON 序列化器 但没有成功 它不断破坏 geo 属性 该属性是 NSNumbers 的 nsarray Post p Post alloc init p uname mike p like
  • 在 HStack 中以正确的方式对齐两个 SwiftUI 文本视图

    我有一个包含两行的简单列表视图 每行包含两个文本视图 查看一和查看二 我想对齐每行中的最后一个标签 查看两个 以便名称标签领先对齐并保持对齐 无论字体大小如何 第一个标签 查看一个 也需要前导对齐 我尝试在第一个标签 查看一个 上设置最小框

随机推荐