2013-03-13 20 views
13

Trong tài liệu của Apple, nó nói:Làm cách nào để tạo một bế tắc trong Grand Central Dispatch?

Chú ý: Bạn không bao giờ nên gọi dispatch_sync hoặc dispatch_sync_f chức năng từ một nhiệm vụ được thực hiện trong cùng một hàng đợi hai người là bạn kế hoạch để vượt qua các chức năng. Điều này đặc biệt quan trọng đối với các hàng đợi nối tiếp , được đảm bảo bế tắc, nhưng cũng nên tránh được cho các hàng đợi đồng thời.

Làm cách nào để bạn viết mã để thực hiện chính xác điều này?

+0

Bạn muốn ví dụ về mã tạo bế tắc? – Vladimir

+0

Có, xin vui lòng, để học tập – BlackMouse

+1

Xem thêm [câu hỏi này] (http://stackoverflow.com/questions/10330679/how-to-dispatch-on-main-queue-synchronously-without-a-deadlock) cho một ví dụ thực tế có thể dễ dàng bế tắc. – zoul

Trả lời

20

Một bế tắc cố ý vào một hàng đợi nhất định:

dispatch_queue_t queue = dispatch_queue_create("my.label", DISPATCH_QUEUE_SERIAL); 
dispatch_async(queue, ^{ 
    dispatch_sync(queue, ^{ 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    }); 

    // this will never be reached 
}); 

Rõ ràng ở đây là các khối bên ngoài và bên trong đang hoạt động trên cùng một hàng đợi. Hầu hết các trường hợp điều này sẽ xảy ra ở những nơi ít rõ ràng hơn những gì người gọi của người gọi dispatch_sync đang hoạt động. Điều này thường xảy ra trong một chồng (lồng nhau) sâu nơi bạn đang thực thi mã trong một số lớp ban đầu được khởi chạy trên một hàng đợi nhất định, và do tai nạn bạn gọi dispatch_sync vào cùng một hàng đợi.

+0

Khi trong bế tắc ... không nên giao diện người dùng không phản hồi? – BlackMouse

+2

@ user1251004 Chỉ khi hàng đợi chính bị chặn. –

+2

Trong ví dụ này chỉ có 'hàng đợi' được tạo bị chặn. Hàng đợi chính vui vẻ tiếp tục chạy. –

7

mã đơn giản mà tạo ra bế tắc:

dispatch_queue_t q = dispatch_queue_create("deadlock queue", DISPATCH_QUEUE_SERIAL); 

NSLog(@"1"); 
dispatch_async(q, ^{ 
    NSLog(@"2"); 
    dispatch_sync(q, ^{ 
     NSLog(@"3"); 
    }); 
    NSLog(@"4"); 
}); 
NSLog(@"5"); 

Log đầu ra:

1 
5 
2 

khối đây nội bộ được dự kiến ​​sẽ được chạy trên hàng đợi serial q nhưng nó không thể chạy cho đến khi khối hiện tại kết thúc, trong khi khối hiện tại, lần lượt, chờ đợi nội bộ để kết thúc khi chúng tôi gọi nó đồng bộ.

4

Cách đơn giản nhất để ngăn chặn là để dispatch_sync trên hàng đợi hiện tại:

dispatch_sync(dispatch_get_current_queue(), ^{}); 

này khối khi hàng đợi hiện nay là một hàng đợi nối tiếp, ví dụ như hàng đợi chính.

0

Trong cú pháp Swift mới nhất:

let queue = DispatchQueue(label: "label") 
queue.async { 
    queue.sync { 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    } 
    // this will never be reached 
} 
Các vấn đề liên quan