• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - 死锁与 `dispatch_barrier`

[复制链接]
菜鸟教程小白 发表于 2022-12-12 11:23:54 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

随着学习dispatch_barrier,我写了一个例子如下:

static dispatch_queue_t queue;
    static dispatch_queue_t readWriteLockQueue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue = dispatch_queue_create("com.test.testasync", DISPATCH_QUEUE_CONCURRENT);
        readWriteLockQueue = dispatch_queue_create("com.test.readWriteLockQueueOfMeta", DISPATCH_QUEUE_CONCURRENT);
    });

    for (NSInteger i=0; i<100; i++) {
        dispatch_async(queue, ^{
            dispatch_sync(readWriteLockQueue, ^{
                NSLog(@"read");
            });

            dispatch_barrier_sync(readWriteLockQueue, ^{
                NSLog(@"write");
            });
        });
    }
    dispatch_barrier_async(queue, ^{
        NSLog(@"finished!");
    });

但是输出是:

2016-05-20 16:23:14.066 Test[23867:781553] read
2016-05-20 16:23:14.066 Test[23867:781555] read
2016-05-20 16:23:14.066 Test[23867:781554] read
2016-05-20 16:23:14.066 Test[23867:781545] read
2016-05-20 16:23:14.066 Test[23867:781559] read
2016-05-20 16:23:14.067 Test[23867:781564] read
2016-05-20 16:23:14.066 Test[23867:781560] read
2016-05-20 16:23:14.066 Test[23867:781561] read
2016-05-20 16:23:14.067 Test[23867:781562] read
2016-05-20 16:23:14.067 Test[23867:781565] read

没有出现write。它超出了我的预期。 所以我需要一些帮助。

dispatch_barrier_syncdispatch_sync 内部没有调用 sync。 为什么会发生死锁?

更新: 感谢@originaluser2 的回答。 我用下面的读写锁更新了我的工具以避免虚拟线程限制。

#define THREAD_ASSERT_ON_ERROR(x_) do { \
_Pragma("clang diagnostic push"); \
_Pragma("clang diagnostic ignored \"-Wunused-variable\""); \
volatile int res = (x_); \
assert(res == 0); \
_Pragma("clang diagnostic pop"); \
} while (0)

    static dispatch_queue_t queue;
    static dispatch_once_t onceToken;
    static pthread_rwlock_t rwlock;
    dispatch_once(&onceToken, ^{
        queue = dispatch_queue_create("com.test.testasync", DISPATCH_QUEUE_CONCURRENT);
        THREAD_ASSERT_ON_ERROR(pthread_rwlock_init(&rwlock, NULL));
    });

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];

    for (NSInteger i=0; i<200; i++) {
        dispatch_async(queue, ^{
            NSString *result = nil;
            THREAD_ASSERT_ON_ERROR(pthread_rwlock_rdlock(&rwlock));
            result = dict[@"test"];
            THREAD_ASSERT_ON_ERROR(pthread_rwlock_unlock(&rwlock));

            if (!result) {
                THREAD_ASSERT_ON_ERROR(pthread_rwlock_wrlock(&rwlock));
                NSLog(@"%ld:try to write",i);
                result = dict[@"test"];
                if (!result) {
                    NSLog(@"%ld:write",i);
                    dict[@"test"] = @"result";
                    result = dict[@"test"];
                }
                THREAD_ASSERT_ON_ERROR(pthread_rwlock_unlock(&rwlock));
            }
            NSLog(@"%ld:%@",i,result);
        });
    }

    dispatch_barrier_sync(queue, ^{});
    NSLog(@"completed");



Best Answer-推荐答案


问题是您要安排 100 个任务同时执行。这将超过虚拟线程限制(通常为 64)——因此您将有 64 个任务坐在那里等待它们的读取或写入完成,但它们无法完成,因为没有更多线程可以执行它们。

如果您将循环减少到 64 个,或者将您的 queue 设置为串行队列以限制任务,代码将再次起作用。虽然,这是一个非常人为的例子。实际上,您永远不会同时发生这么多有争议的读取和写入(这表明您的逻辑中存在更基本的问题)——即使您这样做了,您的写入也很可能是使用 dispatch_barrier_async 异步发生。

关于ios - 死锁与 `dispatch_barrier`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37341738/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap