Penjelasan Daemon Threads

237

Dalam dokumentasi Python dikatakan:

Sebuah utas dapat ditandai sebagai "utas daemon". Signifikansi flag ini adalah bahwa seluruh program Python keluar ketika hanya thread daemon yang tersisa. Nilai awal diwarisi dari untaian pembuatan.

Adakah yang memiliki penjelasan yang lebih jelas tentang apa artinya atau contoh praktis yang menunjukkan di mana Anda akan menetapkan utas daemonic?

Perjelas untuk saya: jadi satu-satunya situasi Anda tidak akan menetapkan utas daemonic, adalah kapan Anda ingin mereka terus berjalan setelah utas utama keluar?

Corey Goldberg
sumber

Jawaban:

448

Beberapa utas melakukan tugas latar belakang, seperti mengirim paket keepalive, atau melakukan pengumpulan sampah berkala, atau apa pun. Ini hanya berguna ketika program utama sedang berjalan, dan tidak apa-apa untuk mematikannya setelah utas lainnya, non-daemon, keluar.

Tanpa utas daemon, Anda harus melacaknya, dan menyuruh mereka keluar, sebelum program Anda dapat sepenuhnya berhenti. Dengan menetapkan mereka sebagai utas daemon, Anda bisa membiarkannya berjalan dan melupakannya, dan ketika program Anda berhenti, semua utas daemon terbunuh secara otomatis.

Chris Jester-Young
sumber
1
Jadi jika saya memiliki utas anak yang menjalankan operasi penulisan file yang diatur ke non-deamon, Apakah itu berarti saya harus membuatnya keluar secara eksplisit?
Ciasto piekarz
8
@san Apa yang dilakukan penulis utas Anda setelah selesai menulis? Apakah hanya kembali? Jika demikian, itu sudah cukup. Daemon threads biasanya untuk hal-hal yang berjalan dalam satu lingkaran dan tidak keluar sendiri.
Chris Jester-Young
Itu tidak melakukan apa-apa, tidak ada pengembalian, satu-satunya tujuan untuk melakukan operasi penulisan file
Ciasto piekarz
2
@san Jika jatuh dari bagian bawah fungsi utas, ia mengembalikan secara implisit.
Chris Jester-Young
Itu mengembalikan Nonedalam kasus itu, tetapi tidak masalah, nilai kembali tidak digunakan.
Chris Jester-Young
30

Katakanlah Anda membuat semacam widget dasbor. Sebagai bagian dari ini, Anda ingin menampilkan jumlah pesan yang belum dibaca di kotak email Anda. Jadi, Anda membuat utas kecil yang akan:

  1. Sambungkan ke server surat dan tanyakan berapa banyak pesan yang belum dibaca yang Anda miliki.
  2. Beri tanda GUI dengan hitungan yang diperbarui.
  3. Tidur sebentar.

Saat widget Anda mulai, itu akan membuat utas ini, menetapkannya sebagai daemon, dan memulainya. Karena ini adalah dasmon, Anda tidak perlu memikirkannya; ketika widget Anda keluar, utas akan berhenti secara otomatis.

John Fouhy
sumber
18

Poster lain memberikan beberapa contoh untuk situasi di mana Anda akan menggunakan utas daemon. Rekomendasi saya, bagaimanapun, jangan pernah menggunakannya.

Ini bukan karena mereka tidak berguna, tetapi karena ada beberapa efek samping buruk yang dapat Anda alami jika Anda menggunakannya. Utas daemon masih bisa dijalankan setelah runtime Python mulai meruntuhkan hal-hal di utas utama, menyebabkan beberapa pengecualian yang cukup aneh.

Info lebih lanjut di sini:

https://joeshaw.org/python-daemon-threads-considered-harmful/

https://mail.python.org/pipermail/python-list/2005-February/343697.html

Sebenarnya Anda tidak pernah membutuhkannya, itu hanya membuat implementasi lebih mudah dalam beberapa kasus.

Joe Shaw
sumber
Masih masalah ini dengan python 3? Tidak ada informasi yang jelas mengenai "pengecualian aneh" ini dalam dokumentasi.
kheraud
5
Dari posting blog Joe: "Pembaruan Juni 2015: Ini adalah bug Python 1856. Diperbaiki dengan Python 3.2.1 dan 3.3, tetapi perbaikannya tidak pernah di-backport ke 2.x. (Upaya untuk backport ke cabang 2.7 menyebabkan bug lain dan itu ditinggalkan.) Utas daemon mungkin ok di Python> = 3.2.1, tapi jelas tidak ada dalam versi sebelumnya. "
clacke
Saya ingin berbagi pengalaman saya di sini: Saya memiliki fungsi yang menelurkan sebagai Thread beberapa kali. Di dalamnya, saya memiliki instance Python loggingdan saya berharap bahwa, setelah menyelesaikan Thread, semua objek (File Descriptor untuk setiap Thread / Fungsi), akan dihancurkan. Pada akhir program saya, saya melihat banyak output seperti IOError: [Errno 24] Too many open files:. Dengan lsof -p pid_of_program, saya menemukan bahwa FD terbuka, bahkan sulit Thread / Fungsi telah menyelesaikan pekerjaan mereka. Penanganan masalah? Menghapus penangan log di akhir fungsi. Jadi daemonicThreads, tidak dapat dipercaya ...
ivanleoncz
17

Cara yang lebih sederhana untuk memikirkannya, mungkin: ketika main kembali, proses Anda tidak akan keluar jika ada utas non-daemon yang masih berjalan.

Sedikit saran: Bersihkan shutdown mudah terjadi kesalahan ketika utas dan sinkronisasi terlibat - jika Anda bisa menghindarinya, lakukanlah. Gunakan daemon utas bila memungkinkan.

Jonathan
sumber
13

Chris sudah menjelaskan apa itu thread daemon, jadi mari kita bicara tentang penggunaan praktis. Banyak implementasi kumpulan utas menggunakan utas daemon untuk pekerja tugas. Pekerja adalah utas yang menjalankan tugas dari antrian tugas.

Pekerja harus terus menunggu tugas dalam antrian tugas tanpa batas karena mereka tidak tahu kapan tugas baru akan muncul. Utas yang memberikan tugas (katakan utas utama) hanya tahu kapan tugas selesai. Utas utama menunggu pada antrian tugas untuk menjadi kosong lalu keluar. Jika pekerja adalah utas pengguna yaitu non-daemon, program tidak akan berakhir. Ini akan terus menunggu pekerja yang berjalan tanpa batas ini, meskipun pekerja tidak melakukan sesuatu yang bermanfaat. Tandai pekerja daemon utas, dan utas utama akan mengurus membunuhnya segera setelah selesai menangani tugas.

Amit
sumber
4
Hati-hati dengan itu! Jika suatu program mengirimkan tugas penting (mis., Perbarui beberapa file "di latar belakang") ke antrian tugas daemon, maka ada risiko bahwa program dapat berakhir sebelum melakukan tugas, atau lebih buruk lagi, di tengah memperbarui file itu.
Solomon Slow
10

Mengutip Chris: "... ketika program Anda berhenti, utas daemon apa pun terbunuh secara otomatis." Saya pikir itu merangkumnya. Anda harus berhati-hati ketika menggunakannya karena mereka tiba-tiba berakhir ketika program utama dieksekusi sampai selesai.

Bas
sumber
4

Ketika utas kedua Anda adalah non-Daemon, utas utama utama aplikasi Anda tidak dapat berhenti karena kriteria keluarnya dikaitkan dengan keluar juga dari utas non-Daemon. Utas tidak dapat dibunuh secara paksa dengan python, oleh karena itu aplikasi Anda harus benar-benar menunggu utas non-Daemon keluar. Jika perilaku ini bukan yang Anda inginkan, maka atur utas kedua Anda sebagai daemon sehingga tidak akan menahan aplikasi Anda untuk keluar.

kebenaranadjustr
sumber