Multithreading dengan Python [Dengan Contoh Pengkodean]
Diterbitkan: 2020-11-30Memperbaiki dan membuat kode lebih cepat adalah langkah berikutnya setelah pengetahuan dasar tentang Python diperoleh. Multithreading adalah salah satu cara untuk mencapai pengoptimalan itu menggunakan "Utas". Apa sajakah ini? Dan bagaimana ini berbeda dari proses? Mari kita cari tahu.
Pada akhir tutorial ini, Anda akan memiliki pengetahuan berikut:
- Apa itu utas dan proses?
- Bagaimana Multithreading dicapai?
- Apa batasannya?
- Kapan Menggunakan Multithreading?
Pelajari kursus ilmu data online dari Universitas top dunia. Dapatkan Program PG Eksekutif, Program Sertifikat Tingkat Lanjut, atau Program Magister untuk mempercepat karier Anda.
Daftar isi
Utas dengan Python
Ketika kita berpikir multitasking, kita berpikir eksekusi paralel. Multithreading bukan eksekusi paralel yang ketat. Utas dapat dianggap sebagai entitas terpisah dari aliran eksekusi dari berbagai bagian program Anda yang berjalan secara independen. Jadi pada dasarnya, utas tidak dieksekusi secara paralel, tetapi Python beralih dari satu utas ke utas lainnya begitu cepat sehingga tampaknya paralel.
Proses di sisi lain sangat paralel dan berjalan pada inti yang berbeda untuk mencapai eksekusi lebih cepat. Utas juga dapat dijalankan pada prosesor yang berbeda, tetapi secara teknis mereka tetap tidak akan berjalan secara paralel.
Dan apakah Anda berpikir jika utas tidak berjalan secara paralel, lalu bagaimana mereka membuat segalanya lebih cepat? Jawabannya adalah mereka tidak selalu membuat pemrosesan lebih cepat. Multithreading secara khusus digunakan dalam tugas-tugas di mana utas akan membuat pemrosesan lebih cepat.
Semua informasi utas terkandung dalam Blok Kontrol Utas (TCB) . TCB terdiri dari bagian-bagian utama berikut:
- TID unik – Pengidentifikasi Utas
- Stack Pointer yang menunjuk ke tumpukan utas dalam proses
- Penghitung Program yang menyimpan alamat instruksi yang sedang dieksekusi oleh utas
- Status Utas (berjalan, siap, menunggu, mulai atau selesai)
Karena itu, proses dapat berisi banyak utas di dalamnya yang berbagi kode, data, dan semua file. Dan semua utas memiliki register dan tumpukan terpisah yang dapat mereka akses.
Sekarang Anda mungkin bertanya-tanya, jika utas menggunakan data dan kode umum, bagaimana mereka semua dapat menggunakannya tanpa menghambat utas lainnya. Ini adalah batasan terbesar dari Multithreading yang akan kita bicarakan nanti dalam tutorial ini.
Pergantian Konteks
Sekarang seperti yang dijelaskan di atas, utas tidak berjalan secara paralel, tetapi sebagai konsekuensinya. Jadi ketika satu utas T1 memulai eksekusi, semua utas lainnya tetap dalam mode menunggu. Hanya setelah T1 selesai dengan eksekusinya, utas antrian lainnya dapat mulai dieksekusi. Python beralih dari satu utas ke utas lainnya begitu cepat sehingga tampak seperti eksekusi paralel. Peralihan ini adalah apa yang kami sebut 'Pengalihan Konteks'.
Pemrograman multithread
Pertimbangkan kode di bawah ini yang menggunakan utas untuk melakukan operasi kubus dan persegi.
benang impor def kubus (n) : print( "Kubus: {}" .format(n * n * n)) def kuadrat (n) : print( "Persegi: {}" .format(n * n)) if __name__ == “__main__” : #buat threadnya t1 = threading.Utas(target=kuadrat, args=( 5 ,)) t2 = threading.Thread(target=cuber, args=( 5 ,)) # mulai utas t1 t1.mulai() #mulai utas t2 t2.mulai() #tunggu sampai t1 selesai t1.bergabung() #tunggu sampai t2 selesai t2.bergabung() # kedua utas selesai print( "Selesai!" ) |
#Keluaran: Persegi: 25 Kubus: 125 Selesai! |
Sekarang mari kita coba memahami kodenya.
Pertama, kami mengimpor modul Threading yang bertanggung jawab untuk semua tugas. Di dalam main, kita membuat 2 thread dengan membuat subclass dari kelas Thread. Kita harus melewati target, yaitu fungsi yang perlu dijalankan di utas itu, dan argumen yang perlu diteruskan ke fungsi-fungsi itu.
Sekarang setelah utas dideklarasikan, kita perlu memulainya. Itu dilakukan dengan memanggil metode start pada utas. Setelah dimulai, program utama perlu menunggu utas untuk menyelesaikan pemrosesannya. Kami menggunakan metode tunggu untuk membiarkan program utama berhenti dan menunggu utas T1 dan T2 menyelesaikan eksekusinya.
Harus Dibaca: Tantangan Python untuk Pemula
Sinkronisasi Utas
Seperti yang telah kita bahas di atas, utas tidak dieksekusi secara paralel, alih-alih Python beralih dari satu ke yang lain. Jadi, ada kebutuhan yang sangat penting untuk sinkronisasi yang benar antara utas untuk menghindari perilaku aneh apa pun.
Kondisi balapan
Utas yang berada di bawah proses yang sama menggunakan data dan file umum yang dapat menyebabkan "Perlombaan" untuk data di antara banyak utas. Oleh karena itu, jika suatu data diakses oleh beberapa utas, itu akan dimodifikasi oleh utas dan hasil yang kami dapatkan tidak akan seperti yang diharapkan. Ini disebut Kondisi Ras.
Jadi, jika Anda memiliki dua utas yang memiliki akses ke data yang sama, maka keduanya dapat mengakses dan memodifikasinya saat utas tertentu dijalankan. Jadi ketika T1 mulai mengeksekusi dan memodifikasi beberapa data, T2 dalam mode sleep/wait. Kemudian T1 menghentikan eksekusi dan masuk ke mode tidur menyerahkan kontrol ke T2, yang juga memiliki akses ke data yang sama. Jadi T2 sekarang akan memodifikasi dan menimpa data yang sama yang akan menyebabkan masalah ketika T1 dimulai lagi.

Tujuan dari Sinkronisasi Utas adalah untuk memastikan Kondisi Balapan ini tidak pernah datang dan bagian penting dari kode diakses oleh utas satu per satu dengan cara yang disinkronkan.
Kunci
Untuk mengatasi dan mencegah Race Condition dan konsekuensinya, modul thread menawarkan kelas Lock yang menggunakan Semaphore untuk membantu sinkronisasi thread. Semaphore tidak lain adalah bendera biner. Anggap mereka sebagai tanda “Terlibat” di bilik Telepon yang memiliki nilai “Terlibat” (setara dengan 1) atau “Tidak Terlibat” (Setara dengan 0). Jadi setiap kali utas menemukan segmen kode dengan kunci, ia harus memeriksa apakah kunci sudah dalam 1 status. Jika ya, maka harus menunggu hingga menjadi 0 agar dapat menggunakannya.
Kelas Lock memiliki dua metode utama:
- mengakuisisi([memblokir]) : Metode memperoleh mengambil dalam pemblokiran parameter sebagai True atau False . Jika kunci untuk utas T1 dimulai dengan pemblokiran sebagai Benar, itu akan menunggu atau tetap diblokir hingga bagian kritis kode dikunci oleh utas T2 lainnya. Setelah utas lain T2 melepaskan kunci, utas T1 memperoleh kunci dan mengembalikan True .
Di sisi lain, jika kunci untuk utas T1 dimulai dengan pemblokiran parameter sebagai False , utas T1 tidak akan menunggu atau tetap diblokir jika bagian kritis sudah dikunci oleh utas T2. Jika melihatnya terkunci, itu akan langsung mengembalikan False dan keluar. Namun, jika kode tidak dikunci oleh utas lain, itu akan memperoleh kunci dan mengembalikan True .
release() : Ketika metode rilis dipanggil pada kunci, itu akan membuka kunci dan mengembalikan True. Juga, itu akan memeriksa apakah ada utas yang menunggu kunci dilepaskan. Jika ada, maka itu akan memungkinkan tepat satu dari mereka untuk mengakses kunci.
Namun, jika kunci sudah dibuka, ThreadError akan muncul.
Kebuntuan
Masalah lain yang muncul ketika kita berurusan dengan banyak kunci adalah – Deadlock. Deadlock terjadi ketika kunci tidak dilepaskan oleh utas karena berbagai alasan. Mari kita pertimbangkan contoh sederhana di mana kita melakukan hal berikut:
benang impor l = threading.Lock() # Sebelum akuisisi pertama l.memperoleh() # Sebelum akuisisi ke-2 l.memperoleh() # Sekarang mendapatkan kunci dua kali |
Dalam kode di atas, kami memanggil metode memperoleh dua kali tetapi tidak melepaskannya setelah diperoleh untuk pertama kalinya. Oleh karena itu, ketika Python melihat pernyataan perolehan kedua, itu akan masuk ke mode tunggu tanpa batas waktu karena kami tidak pernah merilis kunci sebelumnya.
Kondisi kebuntuan ini mungkin menyusup ke dalam kode Anda tanpa Anda sadari. Bahkan jika Anda menyertakan panggilan rilis, kode Anda mungkin gagal di tengah jalan dan rilis tidak akan pernah dipanggil dan kunci akan tetap terkunci. Salah satu cara untuk mengatasinya adalah dengan menggunakan pernyataan with – as , yang juga disebut Manajer Konteks. Menggunakan pernyataan with – as , kunci akan dilepaskan secara otomatis setelah pemrosesan selesai atau gagal karena alasan apa pun.
Baca: Ide & Topik Proyek Python
Sebelum kamu pergi
Seperti yang telah kita bahas sebelumnya, Multithreading tidak berguna di semua aplikasi karena tidak benar-benar membuat semuanya berjalan secara paralel. Tetapi aplikasi utama Multithreading adalah selama tugas I/O di mana CPU diam sambil menunggu data dimuat. Multithreading memainkan peran penting di sini karena waktu idle CPU ini digunakan dalam tugas lain, sehingga membuatnya ideal untuk pengoptimalan.
Jika Anda penasaran untuk belajar tentang ilmu data, lihat Program PG Eksekutif IIIT-B & upGrad dalam Ilmu Data yang dibuat untuk para profesional yang bekerja dan menawarkan 10+ studi kasus & proyek, lokakarya praktis, bimbingan dengan pakar industri, 1 -on-1 dengan mentor industri, 400+ jam pembelajaran dan bantuan pekerjaan dengan perusahaan-perusahaan top.
Apa itu utas dalam Python?
Utas adalah entitas dalam proses yang mungkin dijadwalkan untuk dieksekusi dengan Python. Dalam istilah awam, thread adalah proses perhitungan yang dilakukan oleh komputer. Ini adalah satu set instruksi seperti itu di dalam program yang dapat dijalankan oleh pengembang secara independen dari skrip lain. Utas memungkinkan Anda meningkatkan kecepatan aplikasi dengan menggunakan paralelisme. Ini adalah proses ringan yang akan memungkinkan tugas untuk beroperasi secara paralel. Utas beroperasi secara independen dan memaksimalkan penggunaan CPU, sehingga meningkatkan kinerja CPU.
Apa gunanya multi-utas di Python?
Multithreading adalah teknik threading dalam pemrograman Python yang memungkinkan banyak utas untuk beroperasi secara bersamaan dengan beralih cepat antar utas dengan bantuan CPU (disebut pengalihan konteks). Ketika kami dapat membagi tugas kami menjadi beberapa bagian terpisah, kami menggunakan multithreading. Misalnya, Anda perlu melakukan kueri database yang kompleks untuk mendapatkan data dan memecah kueri tersebut menjadi beberapa kueri individual. Dalam hal ini, akan lebih baik untuk mengalokasikan utas ke setiap kueri dan menjalankan semuanya secara paralel.
Apa itu sinkronisasi utas?
Sinkronisasi utas digambarkan sebagai metode yang menjamin bahwa dua atau lebih proses atau utas bersamaan tidak mengeksekusi bagian penting dari suatu program secara bersamaan. Metode sinkronisasi digunakan untuk mengontrol akses proses ke bagian penting. Saat kami memulai dua atau lebih utas di dalam sebuah program, ada kemungkinan beberapa utas mencoba mengakses sumber daya yang sama, yang menghasilkan hasil yang tidak diharapkan karena tantangan konkurensi. Misalnya, jika banyak utas mencoba menulis dalam file yang sama, data mungkin rusak karena salah satu utas dapat menimpa data, atau ketika satu utas dibuka dan utas lain menutup file yang sama.