菜鸟教程小白 发表于 2022-12-12 11:23:54

ios - 死锁与 `dispatch_barrier`


                                            <p><p>随着学习<code>dispatch_barrier</code>,我写了一个例子如下:</p>

<pre><code>static dispatch_queue_t queue;
    static dispatch_queue_t readWriteLockQueue;
    static dispatch_once_t onceToken;
    dispatch_once(&amp;onceToken, ^{
      queue = dispatch_queue_create(&#34;com.test.testasync&#34;, DISPATCH_QUEUE_CONCURRENT);
      readWriteLockQueue = dispatch_queue_create(&#34;com.test.readWriteLockQueueOfMeta&#34;, DISPATCH_QUEUE_CONCURRENT);
    });

    for (NSInteger i=0; i&lt;100; i++) {
      dispatch_async(queue, ^{
            dispatch_sync(readWriteLockQueue, ^{
                NSLog(@&#34;read&#34;);
            });

            dispatch_barrier_sync(readWriteLockQueue, ^{
                NSLog(@&#34;write&#34;);
            });
      });
    }
    dispatch_barrier_async(queue, ^{
      NSLog(@&#34;finished!&#34;);
    });
</code></pre>

<p>但是输出是:</p>

<pre><code>2016-05-20 16:23:14.066 Test read
2016-05-20 16:23:14.066 Test read
2016-05-20 16:23:14.066 Test read
2016-05-20 16:23:14.066 Test read
2016-05-20 16:23:14.066 Test read
2016-05-20 16:23:14.067 Test read
2016-05-20 16:23:14.066 Test read
2016-05-20 16:23:14.066 Test read
2016-05-20 16:23:14.067 Test read
2016-05-20 16:23:14.067 Test read
</code></pre>

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

<p><code>dispatch_barrier_sync</code> 或 <code>dispatch_sync</code> 内部没有调用 <code>sync</code>。
为什么会发生死锁?</p>

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

<pre><code>#define THREAD_ASSERT_ON_ERROR(x_) do { \
_Pragma(&#34;clang diagnostic push&#34;); \
_Pragma(&#34;clang diagnostic ignored \&#34;-Wunused-variable\&#34;&#34;); \
volatile int res = (x_); \
assert(res == 0); \
_Pragma(&#34;clang diagnostic pop&#34;); \
} while (0)

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

    NSMutableDictionary *dict = ;

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

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

    dispatch_barrier_sync(queue, ^{});
    NSLog(@&#34;completed&#34;);
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>问题是您要安排 100 个任务同时执行。这将超过虚拟线程限制(通常为 64)——因此您将有 64 个任务坐在那里等待它们的读取或写入完成,但它们无法完成,因为没有更多线程可以执行它们。</p>

<p>如果您将循环减少到 64 个,或者将您的 <code>queue</code> 设置为串行队列以限制任务,代码将再次起作用。虽然,这是一个非常人为的例子。实际上,您<em>永远不会</em>同时发生这么多有争议的读取和写入(这表明您的逻辑中存在更基本的问题)——即使您这样做了,您的写入也很可能是使用 <code>dispatch_barrier_async</code> 异步发生。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 死锁与`dispatch_barrier`,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/37341738/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/37341738/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 死锁与 `dispatch_barrier`