Bu soru gevşek bir şekilde ilişkilidir: std :: thread C ++ 11'de havuzlanır mı? . Soru farklı olsa da niyet aynıdır:
Soru 1: Pahalı iş parçacığı oluşturmayı önlemek için kendi iş parçacığı havuzlarınızı (veya üçüncü taraf kitaplığı) kullanmak hala mantıklı mı?
Diğer sorudaki sonuç, std::threadhavuzda toplanmaya güvenemeyeceğinizdir (olabilir ya da olmayabilir). Ancak, std::async(launch::async)havuza alınma şansı çok daha yüksek görünüyor.
Standart tarafından zorlandığını düşünmüyor, ancak IMHO İş parçacığı oluşturma yavaşsa tüm iyi C ++ 11 uygulamalarının iş parçacığı havuzunu kullanmasını beklerdim. Yalnızca yeni bir iş parçacığı oluşturmanın ucuz olduğu platformlarda, her zaman yeni bir iş parçacığı oluşturmalarını beklerdim.
Soru 2: Ben de öyle düşünüyorum, ama bunu ispatlayacak hiçbir gerçeğim yok. Çok iyi yanılıyor olabilirim. Eğitimli bir tahmin mi?
Son olarak, burada ilk önce iş parçacığı oluşturmanın nasıl ifade edilebileceğini gösteren bazı örnek kodlar sağladım async(launch::async):
Örnek 1:
thread t([]{ f(); });
// ...
t.join();
olur
auto future = async(launch::async, []{ f(); });
// ...
future.wait();
Örnek 2: Ateşle ve unut ipliği
thread([]{ f(); }).detach();
olur
// a bit clumsy...
auto dummy = async(launch::async, []{ f(); });
// ... but I hope soon it can be simplified to
async(launch::async, []{ f(); });
Soru 3: asyncVersiyonları versiyonlara tercih eder miydiniz thread?
Gerisi artık sorunun bir parçası değil, yalnızca açıklama için:
Dönüş değeri neden bir kukla değişkene atanmalıdır?
Ne yazık ki, dönüş değerini yakaladığınız mevcut C ++ 11 standart kuvvetleri std::async, aksi takdirde yıkıcı çalıştırılır ve eylem sona erene kadar bloke olur. Bazıları tarafından standartta bir hata olarak kabul edilir (örneğin Herb Sutter tarafından).
Cppreference.com'dan alınan bu örnek bunu güzel bir şekilde göstermektedir:
{
std::async(std::launch::async, []{ f(); });
std::async(std::launch::async, []{ g(); }); // does not run until f() completes
}
Başka bir açıklama:
İş parçacığı havuzlarının başka meşru kullanımları olabileceğini biliyorum, ancak bu soruda yalnızca pahalı iş parçacığı oluşturma maliyetlerinden kaçınma yönüyle ilgileniyorum .
Özellikle kaynaklar üzerinde daha fazla kontrole ihtiyacınız varsa, iş parçacığı havuzlarının çok yararlı olduğu durumlar olduğunu düşünüyorum. Örneğin, bir sunucu, hızlı yanıt sürelerini garantilemek ve bellek kullanımının tahmin edilebilirliğini artırmak için aynı anda yalnızca sabit sayıda isteği işlemeye karar verebilir. İş parçacığı havuzları burada iyi olmalıdır.
İş parçacığı yerel değişkenler kendi iş parçacığı havuzlarınız için bir argüman olabilir, ancak pratikte uygun olup olmadığından emin değilim:
- Başlangıç
std::threaddurumuna getirilmiş iş parçacığı yerel değişkenleri olmadan yeni bir iş parçacığı oluşturma . Belki de istediğin bu değildir. - Tarafından ortaya çıkan dizilerde
async, iş parçacığı yeniden kullanılmış olabileceği için benim için biraz belirsiz. Anladığım kadarıyla, iş parçacığı yerel değişkenlerinin sıfırlanması garanti edilmiyor, ancak yanılıyor olabilirim. - Öte yandan, kendi (sabit boyutlu) iş parçacığı havuzlarınızı kullanmak, gerçekten ihtiyacınız olduğunda size tam kontrol sağlar.
std::async(),. Hala bir iş parçacığı havuzunda önemsiz olmayan evre_yerel yıkıcıları nasıl desteklediklerini merak ediyorum.
launch::async olarak değilse, o zaman sadece öyleymiş gibi davrandığını launch::deferredve asla eşzamansız olarak çalıştırmadığını - yani aslında libstdc ++ sürümünün "seçer" olduğunu gördüm aksi zorlanmadıkça her zaman ertelenmiş kullanmak.
std::asyncperformans için güzel bir şey olabilirdi - doğal olarak bir iş parçacığı havuzuyla desteklenen standart kısa süreli görev yürütme sistemi olabilirdi. Şu anda, std::threadiş parçacığı işlevinin bir değer döndürmesini sağlamak için bazı saçmalıklar üzerinde çalışılıyor. Oh, ve işi std::functiontamamen örtüşen gereksiz "ertelenmiş" işlevsellik eklediler .
std::async(launch::async)havuzda toplanma şansı çok daha yüksek görünüyor." Hayır,std::async(launch::async | launch::deferred)bunun havuza alınabileceğine inanıyorum . Sadecelaunch::asyncgörevin, başka hangi görevlerin çalıştığına bakılmaksızın yeni bir iş parçacığında başlatılması gerekiyor. Politika ilelaunch::async | launch::deferreddaha sonra uygulama hangi politikayı seçer, ancak daha da önemlisi hangi politikayı seçmeyi geciktirir. Diğer bir deyişle, bir iş parçacığı havuzundaki bir iş parçacığı kullanılabilir hale gelene kadar bekleyebilir ve ardından zaman uyumsuz ilkeyi seçebilir.