15

Trong phần Migrating Away from Threads của Hướng dẫn lập trình đồng thời của Apple, có
Changing Producer-Consumer Implementations, tuyên bố rằng việc triển khai biến đa điều kiện đa cấp có thể được đơn giản hóa bằng GCD.Giải pháp sản xuất GCD của người tiêu dùng Apple doc sai?

Với hàng đợi công văn, bạn có thể đơn giản hóa việc sản xuất và tiêu dùng triển khai thành một cuộc gọi duy nhất:

dispatch_async(queue, ^{ 
    // Process a work item. 
}); 

Khi nhà sản xuất của bạn có việc phải làm, tất cả những gì phải làm là thêm công việc đó vào hàng đợi và để hàng đợi xử lý mục.

Vấn đề sản xuất-tiêu dùng còn được gọi là các vấn đề đệm giáp, nhưng làm cho trên không đề cập đến một bộ đệm, ràng buộc của nó hoặc người tiêu dùng, hãy để một mình ngăn chặn các nhà sản xuất & người tiêu dùng để tránh trên/dưới chạy.

Cách này có thể là giải pháp hợp lệ?

+0

Nhưng điều tốt hơn trong trường hợp này chỉ là quan điểm về hiệu suất, có 2 luồng chạy đồng thời nhà sản xuất và người tiêu dùng, bắt đầu trong quá trình khởi động hệ thống hoặc Đi GCD để gửi một chuỗi không đồng bộ khi nhà sản xuất có thêm dữ liệu để thêm (kể từ khi gửi một sợi cũng có thời gian ngọt ngào riêng của nó). – Ichthyocentaurs

+0

Hàng đợi là bộ đệm. –

Trả lời

22

Trong giải pháp decribed tại rằng Apple tài liệu:

  1. Không có đệm bởi vì không có bộ đệm là cần thiết;
  2. Tải hệ thống bị ràng buộc;
  3. Người tiêu dùng là công việc.

Giả sử bạn có nhiều nhà sản xuất và người tiêu dùng, nhà sản xuất đặt dữ liệu vào bộ đệm dùng chung và người tiêu dùng đọc dữ liệu từ bộ đệm dùng chung. Một semaphore hoặc màn hình được sử dụng để đồng bộ hóa quyền truy cập vào bộ đệm được chia sẻ và kích thước bộ đệm được cố định để giới hạn số lượng dữ liệu đang được sản xuất theo tỷ lệ mà chúng đang được tiêu thụ, do đó điều chỉnh nhà sản xuất.

Dưới công văn Grand Central, người tiêu dùng là nhiệm vụ được gửi đến hàng đợi. Vì các tác vụ là các khối Objective-C, nhà sản xuất không cần bộ đệm để cho người tiêu dùng biết về dữ liệu cần xử lý: Các khối Objective-C tự động nắm bắt các đối tượng mà họ tham chiếu.

Ví dụ:

// Producer implementation 
while (…) { 
    id dataProducedByTheProducer; 

    // Produce data and place it in dataProducedByTheProducer 
    dataProducedByTheProducer = …; 

    // Dispatch a new consumer task 
    dispatch_async(queue, ^{ 
     // This task, which is an Objective-C block, is a consumer. 
     // 
     // Do something with dataProducedByTheProducer, which is 
     // the data that would otherwise be placed in the shared 
     // buffer of a traditional, semaphore-based producer-consumer 
     // implementation. 
     // 
     // Note that an Objective-C block automatically keeps a 
     // strong reference to any Objective-C object referenced 
     // inside of it, and the block releases said object when 
     // the block itself is released. 

     NSString *s = [dataProducedByTheProducer …]; 
    }); 
} 

Nhà sản xuất có thể đặt như nhiều nhiệm vụ tiêu dùng như dữ liệu mà nó có thể sản xuất. Tuy nhiên, điều này không có nghĩa là GCD sẽ kích hoạt nhiệm vụ của người tiêu dùng với cùng tốc độ. GCD sử dụng thông tin hệ điều hành để kiểm soát lượng công việc được thực hiện theo tải hệ thống hiện tại. Bản thân nhà sản xuất không được điều chỉnh, và trong hầu hết các trường hợp, nó không phải là do cân bằng tải nội tại của GCD.

Nếu có nhu cầu thực tế để điều tiết nhà sản xuất, một giải pháp là có một tổng thể sẽ gửi n nhiệm vụ của nhà sản xuất và yêu cầu mỗi người tiêu dùng thông báo cho chủ nhân (thông qua công việc được gửi sau khi người tiêu dùng đã hoàn thành công việc của mình) nó đã kết thúc, trong trường hợp đó, tổng thể sẽ gửi một nhiệm vụ sản xuất khác. Ngoài ra, chính người tiêu dùng có thể gửi nhiệm vụ của nhà sản xuất sau khi hoàn thành.

Cụ thể trả lời các mục bạn đã giải quyết:

Vấn đề sản xuất-tiêu dùng còn được gọi là các vấn đề đệm giáp, nhưng làm cho trên không đề cập đến một bộ đệm

Một bộ đệm chia sẻ là không cần thiết vì người tiêu dùng là khối Objective-C, tự động thu thập dữ liệu mà họ tham chiếu.

nó ràng buộc

GCD tiếp giáp với số nhiệm vụ cử theo tải hệ thống hiện tại.

hoặc người tiêu dùng

Người tiêu dùng là những nhiệm vụ cử đến hàng đợi GCD.

hãy để một mình chặn người tiêu dùng sản xuất & để tránh trên/dưới chạy

Không cần để chặn vì không có bộ đệm chia sẻ. Vì mỗi người tiêu dùng là một khối Objective-C nắm bắt dữ liệu được sản xuất thông qua cơ chế chụp bối cảnh khối Objective-C, có mối quan hệ một-một giữa người tiêu dùng và dữ liệu.

+1

Chà, điều này thật tuyệt. Tôi phải suy nghĩ về điều này. Cảm ơn! –

+2

Ok, tôi hiểu ngay bây giờ. Đó là một sự thay đổi tinh thần của các bánh răng đơn giản hóa mọi thứ. Tôi hơi e ngại về hàng đợi mờ đục, mặc dù tôi thấy rằng tôi có thể làm hầu hết mọi thứ tôi có thể làm trước đây, ngoại trừ việc có thể làm giảm các nhiệm vụ tiêu dùng chưa hoàn thành. Tôi muốn sử dụng điều này trong mã mới, nhưng đối với vấn đề tôi đã có trong tâm trí tôi không thể như người tiêu dùng của tôi được lên kế hoạch trên một chủ đề thực sự. Cảm ơn câu trả lời xuất sắc, quá xấu bạn không viết doco. –

+0

Điều tôi không thích về giải pháp này là nhà sản xuất quyết định cách người tiêu dùng tiêu thụ dữ liệu (nó phải xác định khối). Trong khi đó, tôi có thể muốn người tiêu dùng có thể tiêu thụ dữ liệu từ nhiều nơi khác nhau trong mã tùy thuộc vào bước xử lý của nó. – user102008

Các vấn đề liên quan