Apakah pintar mengganti boost :: utas dan boost :: mutex dengan c ++ 11 yang setara?

153

Motivasi: alasan mengapa saya mempertimbangkannya adalah bahwa manajer proyek jenius saya berpikir bahwa dorongan adalah ketergantungan lain dan itu mengerikan karena "Anda bergantung padanya" (Saya mencoba menjelaskan kualitas dorongan, kemudian menyerah setelah beberapa waktu :( Alasan yang lebih kecil mengapa saya ingin melakukannya adalah karena saya ingin mempelajari fitur c ++ 11, karena orang akan mulai menulis kode di dalamnya.

  1. Apakah ada pemetaan 1: 1 antara #include<thread> #include<mutex>dan tingkatkan setara?
  2. Apakah Anda mempertimbangkan ide yang baik untuk mengganti barang tambahan dengan c ++ 11
    barang. Penggunaan saya primitif, tetapi apakah ada contoh ketika std tidak menawarkan peningkatan apa yang dilakukan? Atau (penghujatan) sebaliknya?

PS Saya menggunakan GCC jadi ada header.

NoSenseEtAl
sumber
46
IMO Google pedoman pengkodean itu bodoh dalam banyak hal ... Misalnya. mereka tidak mengizinkan otomatis dari C ++ 11 ... :)
NoSenseEtAl
5
Panduan mengutip: [otomatis] menghambat keterbacaan [karena menghilangkan] memeriksa redundansi (seperti nama jenis) yang mungkin bermanfaat bagi pembaca.
Andrew Tomazos
31
untuk (otomatis = v.begin () ... :)
NoSenseEtAl
15
@ AndrewTomazos-Fathomling: Benarkah? Secara pribadi saya tidak berpikir saya pernah peduli tentang jenis iterator yang sebenarnya (mungkin beberapa kali saja), hanya operasi yang didukung ... Saya berpendapat bahwa redundansi sintaksis jarang merupakan pemikiran yang baik (KERING).
Grizzly
16
btw google memodifikasi panduan bodohnya sehingga sekarang akhirnya mereka memperbolehkan auto
NoSenseEtAl

Jawaban:

192

Ada beberapa perbedaan antara Boost.Thread dan pustaka utas standar C ++ 11:

  • Boost mendukung pembatalan utas, C ++ 11 utas tidak
  • C ++ 11 mendukung std::async, tetapi Boost tidak
  • Boost memiliki boost::shared_mutexpenguncian untuk banyak pembaca / penulis tunggal. Analog yang std::shared_timed_mutexhanya tersedia sejak C ++ 14 ( N3891 ), sementara std::shared_mutexhanya tersedia sejak C ++ 17 ( N4508 ).
  • C ++ 11 timeout berbeda dengan Boost timeout (meskipun ini harus segera berubah sekarang Boost.Chrono telah diterima).
  • Beberapa nama berbeda (misalnya boost::unique_futurevs std::future)
  • Semantik argumen-lewat std::threadberbeda dengan boost::thread--- Meningkatkan penggunaan boost::bind, yang membutuhkan argumen yang dapat disalin. std::threadmemungkinkan tipe hanya pindahkan seperti std::unique_ptruntuk diteruskan sebagai argumen. Karena penggunaan boost::bind, semantik placeholder seperti _1dalam ekspresi terikat bersarang bisa berbeda juga.
  • Jika Anda tidak secara eksplisit memanggil join()atau detach()kemudian boost::threadoperator destruktor dan tugas akan memanggil detach()objek utas yang sedang dihancurkan / ditugaskan. Dengan objek C ++ 11 std::thread, ini akan menghasilkan panggilan ke std::terminate()dan membatalkan aplikasi.

Untuk memperjelas poin tentang parameter hanya bergerak, berikut ini adalah C ++ 11 yang valid, dan mentransfer kepemilikan dari intsementara std::unique_ptrke parameter f1ketika utas baru dimulai. Namun, jika Anda menggunakan boost::threadmaka itu tidak akan berfungsi, seperti yang digunakan secara boost::bindinternal, dan std::unique_ptrtidak dapat disalin. Ada juga bug di pustaka thread C ++ 11 yang disediakan dengan GCC yang mencegah ini berfungsi, seperti yang digunakan std::binddalam implementasi di sana juga.

void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));

Jika Anda menggunakan Boost maka Anda mungkin dapat beralih ke utas C ++ 11 yang relatif tanpa rasa sakit jika kompiler Anda mendukungnya (mis. Versi terbaru GCC di linux memiliki sebagian besar-penyelesaian implementasi dari pustaka ulir C ++ 11 yang tersedia dalam -std=c++0xmode).

Jika kompiler Anda tidak mendukung utas C ++ 11 maka Anda mungkin bisa mendapatkan implementasi pihak ketiga seperti Just :: Thread , tetapi ini masih ketergantungan.

Anthony Williams
sumber
1
Ada metode kunci / buka kunci yang terpisah untuk pembaca dan penulis ( lock/ unlockuntuk penulis vs. 'lock_shared / unlock_shared' untuk pembaca). Banyak pembaca dapat memanggil lock_share tanpa memblokir, selama tidak ada penulis yang menggunakannya.
Dave S
2
The shared_mutexdocs berada di boost.org/doc/libs/1_47_0/doc/html/thread/... . Anda baik mengunci mutex sebagai bersama atau eksklusif, dan kemudian menggunakan fungsi buka kunci yang sesuai. Anda juga dapat menggunakan tipe RAII untuk melakukan ini ( shared_lockmengambil kunci baca bersama, dan lock_guarddan unique_lockmengambil kunci eksklusif). Saya sudah mencoba menjelaskan poin tentang tipe yang hanya bergerak.
Anthony Williams
3
Satu lagi hal kecil yang membuat saya tersandung: dalam boost, destructor dari thread yang berjalan melepaskannya ( boost.org/doc/libs/1_47_0/doc/html/thread/… ), sementara di C ++, destructor dari thread yang menjalankan panggilan dihentikan () (FDIS 30.3.1.3)
Cubbi
3
Di C ++ 11, try_scoped_lockfungsionalitas dicakup oleh std::unique_lock. Ada konstruktor yang mengambil mutex dan std::try_to_lock, dan kemudian akan memanggil try_lock()mutex daripada lock(). Lihat stdthread.co.uk/doc/headers/mutex/unique_lock/…
Anthony Williams
4
Ya, Boost.Thread telah menjadi lebih dekat dengan standar C ++ 11 sejak saya menulis ini, terutama karena karya Vicente Botet.
Anthony Williams
24

std::threadsebagian besar dimodelkan setelahnya boost::thread, dengan beberapa perbedaan :

  • semantik yang tidak dapat disalin, satu-pegangan-peta-ke-satu-os-thread, dipertahankan. Tetapi utas ini dapat dipindahkan untuk memungkinkan utas yang kembali dari fungsi pabrik dan menempatkannya ke dalam wadah.
  • Proposal ini menambah pembatalan boost::thread, yang merupakan komplikasi signifikan. Perubahan ini memiliki dampak besar tidak hanya pada utas tetapi juga pustaka threading C ++ lainnya. Diyakini perubahan besar ini dapat dibenarkan karena manfaatnya.
    • Penghancur utas sekarang harus memanggil membatalkan sebelum melepaskan untuk menghindari bocornya utas bocor ketika utas induk dibatalkan.
    • Anggota detach eksplisit sekarang diperlukan untuk mengaktifkan detached tanpa membatalkan.
  • Konsep pegangan benang dan identitas utas telah dipisahkan menjadi dua kelas (mereka adalah kelas yang sama boost::thread). Ini untuk mendukung manipulasi dan penyimpanan identitas utas yang lebih mudah.
  • Kemampuan untuk membuat id utas yang dijamin untuk membandingkan sama dengan tidak ada utas yang dapat digabung lainnya telah ditambahkan ( boost::threadtidak memilikinya). Ini berguna untuk kode yang ingin tahu apakah sedang dieksekusi oleh utas yang sama dengan panggilan sebelumnya (mutex rekursif adalah contoh nyata).
  • Ada "pintu belakang" untuk mendapatkan pegangan utas asli sehingga klien dapat memanipulasi utas menggunakan OS yang mendasarinya jika diinginkan.

Ini berasal dari 2007, sehingga beberapa poin tidak lagi valid: sekarang boost::threadmemiliki native_handlefungsi, dan, seperti yang ditunjukkan oleh komentator, std::threadtidak ada pembatalan lagi.

Saya tidak dapat menemukan perbedaan yang signifikan antara boost::mutexdan std::mutex.

Alex B
sumber
2
std::threadtidak memiliki pembatalan; memang boost::threadbegitu!
Anthony Williams
@Anthony Anda yakin tidak bermaksud interrupt()untuk meningkatkan :: utas? Tampaknya juga ini proposal asli, yang berubah sejak 2007.
Alex B
4
Ya, pembatalan dorongan disebut "interupsi". Ya, ini proposal lama. Draf publik terbaru dari standar C ++ 11 (yang mencakup pustaka utas) adalah open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
Anthony Williams
6

Ada satu alasan untuk tidak bermigrasi std::thread.

Jika Anda menggunakan tautan statis, std::threadmenjadi tidak dapat digunakan karena bug / fitur gcc ini:

Yaitu, jika Anda menelepon std::thread::detachatau std::thread::joinitu akan menyebabkan pengecualian atau crash, sementara boost::threadberfungsi ok dalam kasus ini.

ks1322
sumber
Saya melihat bahwa satu bug TIDAK DIKONFIRMASI dan yang lainnya adalah INVALID, dengan komentar yang mengatakan bahwa reporter itu harus terhubung libpthread.a. Apakah Anda benar-benar yakin dengan apa yang Anda katakan?
einpoklum
1
@einpoklum, Anda harus dapat membuatnya bekerja dengan menggunakan Wl,--whole-archive -lpthread -Wl,--no-whole-archive, lihat jawaban ini misalnya stackoverflow.com/a/23504509/72178 . Tapi itu bukan cara yang sangat mudah untuk terhubung libpthread.adan juga dianggap sebagai ide buruk.
ks1322
4
Bisakah kita mengasumsikan bug ini diperbaiki karena sekarang 2016? Bug telah diposting pada tahun 2012 dan dari gcc 4.9.2, bug ini secara resmi mendukung C ++ 11 sehingga kami tidak dapat mengeluh C ++ 11 sebelum dukungan resmi.
Splash
6

Kasus Perusahaan

Jika Anda menulis perangkat lunak untuk perusahaan yang perlu dijalankan pada berbagai sistem operasi sedang hingga besar dan akibatnya membangun dengan berbagai kompiler dan versi kompiler (terutama yang relatif lama) pada sistem operasi tersebut, saran saya adalah untuk menjauh dari C ++ 11 semuanya untuk saat ini. Itu berarti Anda tidak dapat menggunakan std::thread, dan saya akan merekomendasikan menggunakan boost::thread.

Kasus Startup Dasar / Teknologi

Jika Anda menulis untuk satu atau dua sistem operasi, Anda tahu pasti bahwa Anda hanya perlu membangun dengan kompiler modern yang sebagian besar mendukung C ++ 11 (mis. VS2015, GCC 5.3, Xcode 7), dan Anda belum tergantung pada dorongan perpustakaan, maka std::threadbisa menjadi pilihan yang bagus.

Pengalaman saya

Saya pribadi menyukai perpustakaan yang diperkeras, banyak digunakan, sangat kompatibel, sangat konsisten seperti dorongan versus alternatif yang sangat modern. Ini terutama berlaku untuk mata pelajaran pemrograman yang rumit seperti threading. Juga, saya telah lama mengalami kesuksesan besar dengan boost::thread(dan meningkatkan secara umum) di berbagai lingkungan, kompiler, model threading, dll. Ketika itu pilihan saya, saya memilih boost.

Nicholas Smith
sumber
1
@ UmNyobe Dia benar juga. Banyak implementasi C ++ 11 threading yang sangat rusak, saya terkejut orang-orang bahkan mempertimbangkan untuk menggunakannya.
StaceyGirl
3

Dengan Visual Studio 2013 std::mutextampaknya berperilaku berbeda dari boost::mutex, yang menyebabkan saya beberapa masalah (lihat pertanyaan ini ).

Robert Hegner
sumber
1

Sehubungan dengan std :: shared_mutex ditambahkan dalam C ++ 17

Jawaban lain di sini memberikan gambaran yang sangat baik tentang perbedaan secara umum. Namun, ada beberapa masalah dengan std::shared_mutexpeningkatan solve tersebut.

  1. Mutices mutakhir. Ini tidak ada std::thread. Mereka memungkinkan pembaca ditingkatkan menjadi penulis tanpa mengizinkan penulis lain masuk sebelum Anda . Ini memungkinkan Anda untuk melakukan hal-hal seperti pra-proses perhitungan besar (misalnya, pengindeksan ulang struktur data) ketika dalam mode baca, kemudian memutakhirkan untuk menulis untuk menerapkan pengindeksan ulang sementara hanya menahan kunci tulis untuk waktu yang singkat.

  2. Keadilan. Jika Anda memiliki aktivitas membaca konstan dengan std::shared_mutex, penulis Anda akan dikunci selama waktu yang tidak terbatas. Ini karena jika ada pembaca lain, mereka akan selalu diberi prioritas. Dengan boost:shared_mutex, semua utas pada akhirnya akan diberikan prioritas. (1) Baik pembaca maupun penulis tidak akan kelaparan.

Ini adalah bahwa jika Anda memiliki sistem throughput yang sangat tinggi tanpa downtime dan pertengkaran yang sangat tinggi, std::shared_mutextidak akan pernah bekerja untuk Anda tanpa secara manual membangun sistem prioritas di atasnya. boost::shared_mutexakan bekerja di luar kotak, meskipun Anda mungkin perlu mengotak-atiknya dalam kasus tertentu. Saya berpendapat bahwa std::shared_mutexperilaku adalah bug laten yang menunggu terjadi di sebagian besar kode yang menggunakannya.

(1) The algoritma yang sebenarnya menggunakan didasarkan pada scheduler OS benang. Dalam pengalaman saya, ketika membaca jenuh, ada jeda yang lebih lama (ketika mendapatkan kunci tulis) di Windows daripada di OSX / Linux.

Robert Fraser
sumber
0

Saya mencoba menggunakan shared_ptr dari std bukannya boost dan saya benar-benar menemukan bug dalam implementasi gcc di kelas ini. Aplikasi saya macet karena destruktor disebut dua kali (kelas ini harus aman thread dan seharusnya tidak menghasilkan masalah seperti itu). Setelah pindah ke boost :: shared_ptr semua masalah hilang. Implementasi C ++ 11 saat ini masih belum matang.

Boost juga memiliki lebih banyak fitur. Misalnya header di versi std tidak menyediakan serializer ke aliran (mis., Cout << durasi). Boost memiliki banyak perpustakaan yang menggunakan sendiri, dll. Yang setara, tetapi tidak bekerja sama dengan versi std.

Singkatnya - jika Anda sudah memiliki aplikasi yang ditulis menggunakan boost, lebih aman untuk menyimpan kode Anda karena bukan berupaya untuk pindah ke standar C ++ 11.

pengguna3323559
sumber
4
The shared_ptrdestructor tidak perlu benang-aman, perilaku itu tidak terdefinisi untuk memiliki satu thread mengakses objek sementara thread lain menghancurkan itu. Jika Anda merasa telah menemukan bug di shared_ptr GCC, harap laporkan , jika tidak, berdasarkan saldo probabilitas Anda salah menggunakannya.
Jonathan Wakely