Apa sebenarnya fungsi Kunci Interpreter Global Python? Apakah bahasa lain yang dikompilasi ke bytecode menggunakan mekanisme serupa?
Apa sebenarnya fungsi Kunci Interpreter Global Python? Apakah bahasa lain yang dikompilasi ke bytecode menggunakan mekanisme serupa?
Jawaban:
Secara umum, untuk masalah keamanan utas apa pun, Anda perlu melindungi struktur data internal dengan kunci. Ini dapat dilakukan dengan berbagai tingkat perincian.
Anda dapat menggunakan penguncian halus, di mana setiap struktur terpisah memiliki kuncinya sendiri.
Anda dapat menggunakan penguncian berbutir kasar di mana satu kunci melindungi semuanya (pendekatan GIL).
Ada berbagai pro dan kontra dari setiap metode. Penguncian mendetail memungkinkan paralelisme yang lebih besar - dua utas dapat dieksekusi secara paralel saat tidak berbagi sumber daya apa pun. Namun ada biaya administrasi yang jauh lebih besar. Untuk setiap baris kode, Anda mungkin perlu memperoleh dan melepaskan beberapa kunci.
Pendekatan berbutir kasar adalah kebalikannya. Dua utas tidak dapat berjalan pada saat yang sama, tetapi utas individu akan berjalan lebih cepat karena tidak melakukan banyak pembukuan. Pada akhirnya itu bermuara pada pertukaran antara kecepatan single-threaded dan paralelisme.
Ada beberapa upaya untuk menghapus GIL dengan python, tetapi biaya tambahan untuk mesin berulir tunggal umumnya terlalu besar. Beberapa kasus sebenarnya bisa lebih lambat bahkan pada mesin multi-prosesor karena pertentangan kunci.
Apakah bahasa lain yang dikompilasi ke bytecode menggunakan mekanisme serupa?
Ini bervariasi, dan mungkin tidak boleh dianggap sebagai properti bahasa sebanyak properti implementasi. Misalnya, ada implementasi Python seperti Jython dan IronPython yang menggunakan pendekatan threading dari VM yang mendasarinya, bukan pendekatan GIL. Selain itu, Ruby versi berikutnya tampaknya bergerak menuju pengenalan GIL.
Berikut ini adalah dari Manual Referensi API Python / C resmi :
Penerjemah Python tidak sepenuhnya aman untuk thread. Untuk mendukung program multi-utas Python, ada kunci global yang harus dipegang oleh utas saat ini sebelum dapat mengakses objek Python dengan aman. Tanpa kunci, bahkan operasi yang paling sederhana pun dapat menyebabkan masalah dalam program multi-thread: misalnya, ketika dua thread secara bersamaan menambah jumlah referensi dari objek yang sama, jumlah referensi bisa bertambah hanya sekali, bukan dua kali.
Oleh karena itu, ada aturan bahwa hanya thread yang telah memperoleh kunci interpreter global yang dapat beroperasi pada objek Python atau memanggil fungsi Python / C API. Untuk mendukung program Python multi-utas, penerjemah secara teratur melepaskan dan memperoleh kembali kunci - secara default, setiap 100 instruksi bytecode (ini dapat diubah dengan sys.setcheckinterval ()). Kunci juga dilepaskan dan diperoleh kembali di sekitar operasi I / O yang berpotensi memblokir seperti membaca atau menulis file, sehingga utas lain dapat berjalan sementara utas yang meminta I / O sedang menunggu operasi I / O selesai.
Saya pikir ini merangkum masalah dengan cukup baik.
Kunci penerjemah global adalah kunci tipe mutex besar yang melindungi penghitung referensi agar tidak disemprot. Jika Anda menulis kode python murni, ini semua terjadi di belakang layar, tetapi jika Anda menyematkan Python ke dalam C, Anda mungkin harus secara eksplisit mengambil / melepaskan kuncinya.
Mekanisme ini tidak terkait dengan Python yang dikompilasi ke bytecode. Ini tidak diperlukan untuk Java. Bahkan, itu bahkan tidak diperlukan untuk Jython (python dikompilasi ke jvm).
lihat juga pertanyaan ini
Python, seperti perl 5, tidak dirancang dari awal agar aman untuk benang. Utas dicangkokkan setelah fakta, sehingga kunci penerjemah global digunakan untuk menjaga pengecualian timbal balik di mana hanya satu utas yang mengeksekusi kode pada waktu tertentu di perut penerjemah.
Utas Python individu secara kooperatif melakukan banyak tugas oleh penerjemah itu sendiri dengan memutar kunci sesering mungkin.
Mengambil kunci sendiri diperlukan ketika Anda berbicara dengan Python dari C ketika utas Python lain aktif untuk 'ikut serta' ke protokol ini dan memastikan tidak ada yang tidak aman terjadi di belakang Anda.
Sistem lain yang memiliki warisan single-threaded yang kemudian berkembang menjadi sistem mulithread sering memiliki mekanisme semacam ini. Misalnya, kernel Linux memiliki "Big Kernel Lock" dari masa awal SMP. Secara bertahap seiring waktu karena kinerja multi-threading menjadi masalah, ada kecenderungan untuk mencoba memecah jenis penguncian ini menjadi bagian-bagian yang lebih kecil atau menggantinya dengan algoritme bebas kunci dan struktur data jika memungkinkan untuk memaksimalkan throughput.
reiserfs
- satu-satunya alasan sebenarnya yang saya tahu sama sekali).
Mengenai pertanyaan kedua Anda, tidak semua bahasa skrip menggunakan ini, tetapi itu hanya membuatnya kurang kuat. Misalnya, thread di Ruby berwarna hijau dan bukan native.
Dalam Python, utas adalah asli dan GIL hanya mencegahnya berjalan pada inti yang berbeda.
Di Perl, utasnya bahkan lebih buruk. Mereka hanya menyalin seluruh interpreter, dan jauh dari dapat digunakan seperti di Python.
Mungkin ini artikel oleh BDFL akan membantu.