iOS中的操作同步挑战

时间:2015-07-02 09:32:47

标签: ios swift grand-central-dispatch semaphore

我有3个操作:ABC

  • AB可以同时处理
  • 如果C运行,AB应该等待
  • 如果AB运行C应等待

我会用调度组和信号量来解决它:

public var dgLoadMain = dispatch_group_create()
public var semaLoadMain = dispatch_semaphore_create(1)

AB看起来像这样:

dispatch_group_enter(dgLoadMain)
dispatch_semaphore_wait(semaLoadMain, DISPATCH_TIME_FOREVER)
dispatch_semaphore_signal(semaLoadMain) //maybe odd, but right after wait, it signals, it just check wether C is in critical section, if not, release semaphore, and let other B or A continue too
//..
dispatch_group_leave(dgLoadMain)

C看起来像这样:

dispatch_group_wait(dgLoadMain, DISPATCH_TIME_FOREVER)
dispatch_semaphore_wait(semaLoadMain, DISPATCH_TIME_FOREVER)
//..
dispatch_semaphore_signal(semaLoadMain)

你觉得还可以吗?

2 个答案:

答案 0 :(得分:1)

<div class="item w2"> <script type="text/javascript"> $(function() { if ($('.w2').length) { console.log('The class is applied!'); } else { console.log('The class is not applied'); } }); </script> 更复杂。看看这段代码。它是Objective-C,但同样的概念在Swift上绝对有效。

dispatch_barrier_async

结果。

#import <Foundation/Foundation.h>

void A()
{
    NSLog(@"A begin");
    sleep(1);
    NSLog(@"A end");
}

void B()
{
    NSLog(@"B begin");
    sleep(1);
    NSLog(@"B end");
}

void C()
{
    NSLog(@"C begin");
    sleep(1);
    NSLog(@"C end");
}

int main()
{
    dispatch_queue_t q = dispatch_queue_create("ABC", DISPATCH_QUEUE_CONCURRENT);

    dispatch_queue_t qA = dispatch_queue_create("A", DISPATCH_QUEUE_SERIAL);
    dispatch_set_target_queue(qA, q);

    dispatch_queue_t qB = dispatch_queue_create("B", DISPATCH_QUEUE_SERIAL);
    dispatch_set_target_queue(qB, q);

    dispatch_barrier_async(q, ^{C();});
    dispatch_async(qA, ^{A();});
    dispatch_async(qA, ^{A();});
    dispatch_async(qB, ^{B();});
    dispatch_barrier_async(q, ^{C();});
    dispatch_async(qB, ^{B();});
    dispatch_barrier_async(q, ^{C();});
    dispatch_async(qA, ^{A();});

    dispatch_main();
    return 0;
}

答案 1 :(得分:0)

你的解决方案可能有效,但推理它的正确性是痛苦的。我提出了我认为更清洁的解决方案。它使用2个信号量。它基本上将任务A和任务B结合起来,并将它们视为一项任务。然后它使用timeout属性来检查任务A或任务B之前是否已完成,并相应地向第一个信号量发送信号。这是代码:

let semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
let ABSema = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    print("A")
    if !Bool(dispatch_semaphore_wait(ABSema, DISPATCH_TIME_NOW))
    {
        dispatch_semaphore_signal(ABSema)
    }
    else
    {
        dispatch_semaphore_signal(semaphore)
    }

})
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    print("B")
    if !Bool(dispatch_semaphore_wait(ABSema, DISPATCH_TIME_NOW))
    {
        dispatch_semaphore_signal(ABSema)
    }
    else
    {
        dispatch_semaphore_signal(semaphore)
    }
})


dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    print("C")
    dispatch_semaphore_signal(semaphore)
})