Saya seorang programmer yang cukup baik, bos saya juga seorang programmer yang cukup baik. Meskipun ia tampaknya meremehkan beberapa tugas seperti multi-threading dan betapa sulitnya hal itu (saya merasa sangat sulit untuk hal lain selain menjalankan beberapa utas, menunggu semuanya selesai, lalu mengembalikan hasil).
Saat Anda mulai harus khawatir tentang kebuntuan dan kondisi balapan, saya merasa sangat sulit, tetapi bos tampaknya tidak menghargai ini - saya tidak berpikir dia pernah menemukan ini. Hanya menampar kunci di atasnya cukup banyak sikap.
Jadi bagaimana saya bisa memperkenalkannya, atau menjelaskan mengapa ia mungkin meremehkan kompleksitas konkurensi, paralelisme, dan multi-threading? Atau mungkin saya salah?
Sunting: Hanya sedikit tentang apa yang telah dia lakukan - loop melalui daftar, untuk setiap item dalam daftar itu buat utas yang mengeksekusi perintah pembaruan basis data berdasarkan informasi dalam item itu. Saya tidak yakin bagaimana dia mengendalikan berapa banyak thread yang dieksekusi sekaligus, saya kira dia pasti telah menambahkannya ke antrian jika ada terlalu banyak yang berjalan (dia tidak akan menggunakan semaphore).
sumber
Jawaban:
Jika Anda dapat mengandalkan pengalaman matematika apa pun, ilustrasikan bagaimana aliran eksekusi normal yang pada dasarnya deterministik menjadi tidak hanya tidak deterministik dengan beberapa utas, tetapi kompleks secara eksponensial , karena Anda harus memastikan setiap interleaving instruksi mesin yang mungkin masih akan melakukan hal yang benar. Contoh sederhana dari pembaruan yang hilang atau situasi membaca kotor sering kali membuka mata.
"Menampar kunci" adalah solusi sepele ... itu menyelesaikan semua masalah Anda jika Anda tidak peduli dengan kinerja. Cobalah untuk mengilustrasikan seberapa besar kinerja yang akan terjadi jika, misalnya, Amazon harus mengunci seluruh pantai timur setiap kali seseorang di Atlanta memesan satu buku!
sumber
Multi-threading adalah sederhana. Pengodean aplikasi untuk multi-threading sangat, sangat mudah.
Ada trik sederhana, dan ini adalah dengan menggunakan antrian pesan yang dirancang dengan baik (jangan tidak roll sendiri) untuk melewati data antara benang.
Bagian yang sulit adalah mencoba membuat beberapa utas secara ajaib memperbarui objek yang dibagikan dengan beberapa cara. Saat itulah ia rawan kesalahan karena orang-orang tidak memperhatikan kondisi balapan yang ada.
Banyak orang tidak menggunakan antrian pesan dan mencoba memperbarui objek yang dibagikan dan membuat masalah sendiri.
Yang menjadi sulit adalah merancang algoritma yang berfungsi dengan baik ketika mengirimkan data di antara beberapa antrian. Itu sulit. Tetapi mekanisme utas yang ada bersama (melalui antrian bersama) mudah.
Juga, perhatikan bahwa utas berbagi sumber daya I / O. Program terikat I / O (mis., Koneksi jaringan, operasi file atau operasi basis data) tidak mungkin berjalan lebih cepat dengan banyak utas.
Jika Anda ingin mengilustrasikan masalah pembaruan objek yang dibagikan, itu mudah. Duduk di seberang meja dengan seikat kartu kertas. Tuliskan satu set perhitungan sederhana - 4 atau 6 formula sederhana - dengan banyak ruang di halaman.
Ini permainannya. Anda masing-masing membaca rumus, menulis jawaban dan meletakkan kartu dengan jawabannya.
Anda masing-masing akan melakukan setengah pekerjaan, bukan? Anda sudah selesai separuh waktu, bukan?
Jika bos Anda tidak banyak berpikir dan baru mulai, Anda akan berakhir dengan pertentangan dalam beberapa cara dan keduanya menulis jawaban untuk rumus yang sama. Itu tidak berhasil karena ada kondisi ras yang melekat di antara Anda berdua membaca sebelum menulis. Tidak ada yang menghentikan Anda dari keduanya membaca formula yang sama dan menimpa jawaban masing-masing.
Ada banyak, banyak cara untuk menciptakan kondisi balapan dengan sumber daya yang buruk atau tidak terkunci.
Jika Anda ingin menghindari semua konflik, Anda memotong kertas menjadi tumpukan formula. Anda mengambil satu dari antrian, menuliskan jawabannya, dan memposting jawabannya. Tidak ada konflik karena Anda berdua membaca dari antrian pesan hanya satu pembaca.
sumber
Pemrograman multi-threaded mungkin merupakan solusi paling sulit untuk konkurensi. Ini pada dasarnya adalah abstraksi level rendah dari apa yang sebenarnya dilakukan mesin.
Ada sejumlah pendekatan, seperti model aktor atau memori transaksional (perangkat lunak) , yang jauh lebih mudah. Atau bekerja dengan struktur data yang tidak dapat diubah (seperti daftar dan pohon).
Secara umum, pemisahan keprihatinan yang tepat membuat multi-threading lebih mudah. Sesuatu, yang sering terlupakan, ketika orang menelurkan 20 utas, semua berusaha memproses buffer yang sama. Gunakan reaktor di mana Anda memerlukan sinkronisasi dan umumnya mengirimkan data antara pekerja yang berbeda dengan antrian pesan.
Jika Anda memiliki kunci dalam logika aplikasi Anda, Anda melakukan sesuatu yang salah.
Jadi ya, secara teknis, multi-threading sulit.
"Menampar kunci di atasnya" adalah solusi yang paling tidak dapat diskalakan untuk masalah konkurensi, dan sebenarnya mengalahkan seluruh tujuan multi-threading. Apa yang dilakukannya adalah mengembalikan masalah kembali ke model eksekusi non-konkuren. Semakin banyak Anda melakukannya, semakin besar kemungkinannya, bahwa Anda hanya memiliki satu utas berjalan pada saat itu (atau 0 dalam kebuntuan). Itu mengalahkan seluruh tujuan.
Ini seperti mengatakan "Memecahkan masalah dunia ke-3 itu mudah. Hanya melempar bom ke atasnya." Hanya karena ada solusi sepele, ini tidak membuat masalah sepele, karena Anda peduli dengan kualitas hasilnya.
Namun dalam praktiknya, menyelesaikan masalah ini sama sulitnya dengan masalah pemrograman lainnya dan paling baik dilakukan dengan abstraksi yang sesuai. Yang membuatnya sebenarnya cukup mudah.
sumber
Saya pikir ada sudut pandang non teknis untuk pertanyaan ini - IMO ini masalah kepercayaan. Kami biasanya diminta untuk mereproduksi aplikasi yang kompleks seperti - oh, saya tidak tahu - Facebook misalnya. Saya sampai pada kesimpulan bahwa jika Anda harus menjelaskan kompleksitas tugas kepada yang belum tahu / manajemen - maka ada sesuatu yang busuk di Denmark.
Bahkan jika programmer ninja lain dapat melakukan tugas dalam 5 menit, perkiraan Anda didasarkan pada kemampuan pribadi Anda. Teman bicara Anda harus belajar untuk mempercayai pendapat Anda tentang masalah ini atau mempekerjakan seseorang yang kata-katanya ingin mereka terima.
Tantangannya bukan dalam menyampaikan implikasi teknis, yang orang cenderung abaikan atau tidak dapat pahami melalui percakapan, tetapi dalam membangun hubungan yang saling menghormati.
sumber
Salah satu eksperimen pemikiran sederhana untuk memahami kebuntuan adalah masalah " filsuf makan ". Salah satu contoh yang cenderung saya gunakan untuk menggambarkan bagaimana kondisi balapan yang buruk adalah situasi Therac 25 .
"Hanya menampar kunci" adalah mentalitas seseorang yang belum menemukan bug yang sulit dengan multi-threading. Dan mungkin saja dia berpikir Anda melebih-lebihkan keseriusan situasi (saya tidak - mungkin untuk meledakkan barang atau membunuh orang dengan bug kondisi ras, terutama dengan perangkat lunak tertanam yang berakhir di mobil).
sumber
Aplikasi bersamaan tidak deterministik. Dengan sejumlah kecil keseluruhan kode yang telah diakui oleh programmer sebagai rentan, Anda tidak dapat mengontrol kapan bagian dari utas / proses dijalankan dalam kaitannya dengan bagian mana pun dari utas lainnya. Pengujian lebih sulit, membutuhkan waktu lebih lama, dan tidak mungkin menemukan semua cacat terkait konkurensi. Cacat, jika ditemukan, seringkali halus tidak dapat direproduksi secara konsisten, maka memperbaiki itu sulit.
Oleh karena itu satu-satunya aplikasi konkuren yang benar adalah yang terbukti benar, sesuatu yang tidak sering dilakukan dalam pengembangan perangkat lunak. Akibatnya, jawaban oleh S.Lot adalah saran umum terbaik, karena pesan yang lewat relatif mudah dibuktikan benar.
sumber
Jawaban singkat dalam dua kata: NONDETERMINISME YANG DAPAT DITERIMA
Jawaban panjang: Itu tergantung pada pendekatan mana untuk pemrograman bersamaan yang Anda gunakan mengingat masalah Anda. Dalam buku Konsep, Teknik, dan Model Pemrograman Komputer , penulis dengan jelas menjelaskan empat pendekatan praktis utama untuk menulis program bersamaan:
Sekarang yang paling mudah dari keempat pendekatan ini selain dari pemrograman sekuensial yang jelas adalah deklaratif konkurensi , karena program yang ditulis menggunakan pendekatan ini tidak memiliki nondeterminisme yang dapat diamati . Dengan kata lain, tidak ada kondisi ras , karena kondisi ras hanyalah perilaku nondeterministik yang dapat diamati.
Tetapi kurangnya nondeterminisme yang dapat diamati berarti, bahwa ada beberapa masalah yang tidak dapat kita atasi dengan menggunakan konkurensi deklaratif. Di sinilah dua pendekatan terakhir tidak begitu mudah ikut bermain. Bagian yang tidak mudah adalah konsekuensi dari nondeterminisme yang dapat diamati. Sekarang mereka berdua jatuh di bawah model konkuren stateful dan juga setara dalam ekspresif. Tetapi karena jumlah core yang terus meningkat per CPU, tampaknya industri baru-baru ini lebih tertarik pada konkurensi lewat pesan, seperti dapat dilihat pada naiknya pustaka lewat pesan (misalnya Akka untuk JVM) atau bahasa pemrograman (misalnya Erlang ) .
Pustaka Akka yang disebutkan sebelumnya, yang didukung oleh model Aktor teoritis menyederhanakan membangun aplikasi bersamaan, karena Anda tidak perlu lagi berurusan dengan kunci, monitor, atau transaksi. Di sisi lain itu membutuhkan pendekatan yang berbeda untuk merancang solusi, yaitu berpikir dengan cara bagaimana secara hierarkis menggabungkan aktor. Orang bisa mengatakan bahwa itu membutuhkan pola pikir yang sama sekali berbeda, yang lagi-lagi dapat menjadi lebih sulit daripada menggunakan konkurensi berbagi keadaan biasa.
Pemrograman bersamaan sulit dilakukan karena nondeterminisme yang dapat diamati, tetapi ketika menggunakan pendekatan yang tepat untuk masalah yang diberikan dan perpustakaan yang tepat yang mendukung pendekatan itu, maka banyak masalah dapat dihindari.
sumber
Saya pertama kali diajarkan bahwa hal itu dapat memunculkan masalah dengan melihat program sederhana yang memulai 2 utas dan membuat keduanya mencetak ke konsol pada waktu yang bersamaan dari 1-100. Dari pada:
Anda mendapatkan sesuatu yang lebih seperti ini:
Jalankan lagi dan Anda mungkin mendapatkan hasil yang sama sekali berbeda.
Sebagian besar dari kita telah dilatih untuk mengasumsikan bahwa kode kita akan dieksekusi secara berurutan. Dengan kebanyakan multi-threading kita tidak bisa menerima ini begitu saja "di luar kotak".
sumber
Coba gunakan beberapa palu untuk tumbuk dalam sekelompok paku yang berjarak dekat sekaligus tanpa komunikasi antara mereka yang memegang palu ... (asumsikan bahwa mereka ditutup mata).
Tingkatkan ini untuk membangun rumah.
Sekarang cobalah tidur di malam hari membayangkan Anda adalah arsiteknya. :)
sumber
Bagian yang mudah: gunakan multithreading dengan fitur kerangka kerja kontemporer, sistem operasi dan perangkat keras, seperti semaphore, antrian, penghitung yang saling bertautan, jenis kotak atom dll.
Bagian yang sulit: mengimplementasikan fitur-fitur itu sendiri tanpa menggunakan fitur di tempat pertama, mungkin kecuali beberapa kemampuan perangkat keras yang sangat terbatas, hanya mengandalkan jaminan pencatatan jam kerja yang koherensi di berbagai core.
sumber