Search code examples
swiftgrand-central-dispatch

lock and unlock dispatch_queue_t in async task


I want lock LockQueue2 to complete process and when unlock LockQueue2 show "number is :" number in dispatch_after.

I need this output :

number set value 1
number is 1
number set value 2
number is 2
number set value 3
number is 3

let LockQueue = dispatch_queue_create("LockQueue", nil)

func test(num :Int){
  var number = 0
  let LockQueue2 = dispatch_queue_create("LockQueue2", nil)

  dispatch_async(LockQueue){
    LockQueue2.lock()
    // any process or waiting
    sleep(2)
    dispatch_sync(LockQueue2) {
             number = num
             print("number set value ", number)
           LockQueue2.unlock()
    }
  } 
  dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)){
     // any process or waiting
     sleep(3)
     dispatch_after(LockQueue2) {
         print("number is :", number)//*** show number set in last dispatch ***            
     } 
  }          
 }

test(1)
test(2)
test(3)

Solution

  • If you're dealing with simple synchronous tasks, like you are, you can just use a serial queue:

    let queue = DispatchQueue(label: "com.domain.app.serialqueue")
    var number = 0
    
    func simpleSerialQueue(_ num: Int) {
        queue.async { [self] in
            Thread.sleep(forTimeInterval: 2)
            number = num
            print("number set value: ", number)
        }
    
        queue.async { [self] in
            let value = number
            DispatchQueue.global(qos: .background).async {
                print("number is:", value) //*** show number set in last dispatch ***
            }
        }
    }
    
    simpleSerialQueue(1)
    simpleSerialQueue(2)
    simpleSerialQueue(3)
    

    As you can see, I would let the queue coordinate my process, excising the use of semaphores or the like, which can be easily misused and result in deadlocks.

    If the process in these tasks was, itself asynchronous, it might beg for other patterns (Combine, custom asynchronous Operation subclasses, etc.). But for simple synchronous tasks like this, a serial dispatch queue is adequate.


    See previous revision of this answer for Swift 2 rendition.