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::thread
havuzda 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: async
Versiyonları 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::thread
durumuna 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::deferred
ve 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::async
performans 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::thread
iş 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::function
tamamen ö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::async
gö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::deferred
daha 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.