İş parçacığını doğru şekilde sonlandırmam veya bir "sonlandırma" komutuna yanıt vermem gerekmiyor. İş parçacığını saf C ++ 11 kullanarak zorla sonlandırmakla ilgileniyorum.
İş parçacığını doğru şekilde sonlandırmam veya bir "sonlandırma" komutuna yanıt vermem gerekmiyor. İş parçacığını saf C ++ 11 kullanarak zorla sonlandırmakla ilgileniyorum.
Yanıtlar:
std::terminate()
Herhangi bir iş parçacığından çağrı yapabilirsiniz ve bahsettiğiniz iş parçacığı zorla sona erecektir.
~thread()
Hedef iş parçacığının nesnesi üzerinde, müdahale etmeden join()
veya detach()
bu nesne üzerinde çalıştırılmayı ayarlayabilirsiniz . Bu, 1. seçenek ile aynı etkiye sahip olacaktır.
Bir istisna atan bir yıkıcıya sahip bir istisna tasarlayabilirsiniz. Ve sonra, hedef iş parçacığının, zorla sonlandırılması gerektiğinde bu istisnayı atmasını ayarlayın. Bunun zor kısmı, hedef iş parçacığının bu istisnayı atmasını sağlamaktır.
Seçenekler 1 ve 2, süreç içi kaynakları sızdırmaz, ancak her iş parçacığını sonlandırırlar .
Seçenek 3 muhtemelen kaynakları sızdıracaktır, ancak hedef iş parçacığının istisnayı atmayı kabul etmesi gerektiği için kısmen işbirlikçi.
C ++ 11'de (bildiğim kadarıyla) çok iş parçacıklı bir programda tek bir iş parçacığını işbirliği yapmadan öldürmenin (yani tüm iş parçacıklarını öldürmeden) taşınabilir bir yolu yoktur. Böyle bir özelliği tasarlamak için hiçbir motivasyon yoktu.
A std::thread
şu üye işlevine sahip olabilir:
native_handle_type native_handle();
İstediğinizi yapmak için işletim sistemine bağlı bir işlevi çağırmak için bunu kullanabilirsiniz. Örneğin, Apple'ın işletim sistemlerinde bu işlev vardır ve native_handle_type
bir pthread_t
. Başarılı olursanız, kaynakları sızdırmanız olasıdır.
std::terminate
ne statik yıkıcıları çağırır ne de çıktı arabelleklerini temizler, bu nedenle kaynakların serbest bırakılma sırası iyi tanımlanmamıştır ve herhangi bir verinizin kullanıcı tarafından görülebilir veya kalıcı bir depoya yazılması konusunda herhangi bir garantiniz veya hatta tutarlı ve eksiksiz.
exit()
veya abort()
aynı genel etkiye sahip olabilirsiniz.
@Howard Hinnant cevabı doğru hem de ve kapsamlı. Ancak çok hızlı std::terminate()
okunursa yanlış anlaşılabilir, çünkü (tüm süreç) @AlexanderVX'in aklındaki "sonlandırıcı" ile aynı adı taşıyor (1 iş parçacığı).
Özet: "1 iş parçacığını sonlandır + zorla (hedef iş parçacığı işbirliği yapmaz) + saf C ++ 11 = Olmaz."
std::terminate()
cevap klasik bir yaramaz Djinn hikayesi gibidir; o şekilde muhtemelen rağmen, mektuba OP'ın isteği her şeyi değil karşılamaktadır geliyordu . Mütevazı mizah beni güldürdü. :-)
Bu soru aslında daha derin bir yapıya sahiptir ve genel olarak çok iş parçacıklı kavramları iyi anlamak size bu konu hakkında fikir verecektir. Aslında, bunları kullanmamanız için uyarı vermeden eşzamansız aniden iş parçacığı sonlandırma olanakları sağlayan herhangi bir dil veya işletim sistemi yoktur. Ve tüm bu yürütme ortamları, geliştiriciye şiddetle tavsiye eder ve hatta işbirlikli veya eşzamanlı iş parçacığı sonlandırma temelinde çok iş parçacıklı uygulamalar oluşturmayı gerektirir. Bu ortak kararların ve tavsiyelerin nedeni, hepsinin aynı genel çok iş parçacıklı model temelinde inşa edilmesidir.
İkincisinin avantajlarını ve sınırlamalarını daha iyi anlamak için çoklu işlem ve çoklu okuma kavramlarını karşılaştıralım.
Çoklu işlem, tüm yürütme ortamının işletim sistemi tarafından kontrol edilen tamamen yalıtılmış süreçler kümesine bölündüğünü varsayar. Süreç, işlemin yerel belleği ve içindeki veriler ve dosyalar, soketler, senkronizasyon nesneleri gibi tüm sistem kaynakları dahil olmak üzere yürütme ortamı durumunu birleştirir ve izole eder. İzolasyon, sürecin kritik öneme sahip bir özelliğidir, çünkü hataların süreç sınırları tarafından yayılmasını sınırlar. Başka bir deyişle, hiçbir süreç sistemdeki başka bir sürecin tutarlılığını etkilemez. Aynısı işlem davranışı için de geçerlidir, ancak daha az kısıtlı ve daha bulanık bir şekilde. Böyle bir ortamda, herhangi bir süreç herhangi bir "keyfi" anda sonlandırılabilir, çünkü ilk olarak her işlem izole edilir, ikincisi,
Buna karşılık, çoklu okuma, aynı işlemde birden çok iş parçacığı çalıştırdığını varsayar. Ancak tüm bu iş parçacıkları aynı izolasyon kutusunu paylaşır ve sürecin dahili durumuna ilişkin herhangi bir işletim sistemi kontrolü yoktur. Sonuç olarak, herhangi bir iş parçacığı genel işlem durumunu değiştirebilir ve bozabilir. Aynı zamanda, iş parçacığının durumunun bir iş parçacığını tamamen öldürmek için güvenli olduğu iyi bilinen noktalar uygulama mantığına bağlıdır ve ne işletim sistemi ne de programlama dili çalışma zamanı için bilinmemektedir. Sonuç olarak, keyfi anda iş parçacığı sonlandırma, yürütme yolunun keyfi bir noktasında onu öldürmek anlamına gelir ve süreç genelinde veri bozulmasına, belleğe ve sızıntıya kolayca yol açabilir,
Bu nedenle ortak yaklaşım, geliştiricileri eşzamanlı veya işbirliğine dayalı iş parçacığı sonlandırmayı uygulamaya zorlamaktır; burada bir iş parçacığı başka bir iş parçacığı sonlandırmayı talep edebilir ve iyi tanımlanmış bir noktadaki diğer iş parçacığı bu isteği kontrol edebilir ve iyi tanımlanmış durumdan kapatma prosedürünü başlatabilir. tüm küresel sistem çapında kaynakların ve yerel süreç çapındaki kaynakların güvenli ve tutarlı bir şekilde serbest bırakılmasıyla.
C ++ iş parçacığını sonlandırmak için işletim sistemine bağlı işlevi kullanmanın ipuçları:
std::thread::native_handle()
join()
veya çağrılmadan önce yalnızca iş parçacığının geçerli yerel tutamaç türünü alabilir detach()
. Bundan sonra native_handle()
0 döndürür - pthread_cancel()
coredump olacaktır.
Yerel iş parçacığı sonlandırma işlevini etkin bir şekilde çağırmak için (örneğin pthread_cancel()
), std::thread::join()
veya std::thread::detach()
. Böylece yerel sonlandırıcınız her zaman kullanılacak geçerli bir yerel tutamaç sahibi olur.
Daha fazla açıklama için lütfen bakınız: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
Sanırım öldürülmesi gereken iş parçacığı ya herhangi bir bekleme modunda ya da ağır bir iş yapıyor. "Saf" bir yol kullanmanızı öneririm.
Bazı global boole tanımlayın:
std::atomic_bool stop_thread_1 = false;
Aşağıdaki kodu (veya benzerini), çağrı yığınındaki tüm işlevlerin evre doğal olarak sona erene kadar geri dönmesine neden olacak şekilde birkaç anahtar noktaya yerleştirin:
if (stop_thread_1)
return;
Ardından iş parçacığını başka bir (ana) iş parçacığından durdurmak için:
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)