dispatch_sync vs. dispatch_async on main queue

前端 未结 3 1317
北恋
北恋 2021-01-29 23:20

Bear with me, this is going to take some explaining. I have a function that looks like the one below.

Context: \"aProject\" is a Core Data entity named LPProject with an

3条回答
  •  面向向阳花
    2021-01-30 00:13

    This is a common issue related to disk I/O and GCD. Basically, GCD is probably spawning one thread for each file, and at a certain point you've got too many threads for the system to service in a reasonable amount of time.

    Every time you call dispatch_async() and in that block you attempt to to any I/O (for example, it looks like you're reading some files here), it's likely that the thread in which that block of code is executing will block (get paused by the OS) while it waits for the data to be read from the filesystem. The way GCD works is such that when it sees that one of its worker threads is blocked on I/O and you're still asking it to do more work concurrently, it'll just spawn a new worker thread. Thus if you try to open 50 files on a concurrent queue, it's likely that you'll end up causing GCD to spawn ~50 threads.

    This is too many threads for the system to meaningfully service, and you end up starving your main thread for CPU.

    The way to fix this is to use a serial queue instead of a concurrent queue to do your file-based operations. It's easy to do. You'll want to create a serial queue and store it as an ivar in your object so you don't end up creating multiple serial queues. So remove this call:

    dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    Add this in your init method:

    taskQ = dispatch_queue_create("com.yourcompany.yourMeaningfulLabel", DISPATCH_QUEUE_SERIAL);

    Add this in your dealloc method:

    dispatch_release(taskQ);

    And add this as an ivar in your class declaration:

    dispatch_queue_t taskQ;

提交回复
热议问题