Kumpulan Thread

Kumpulan utas adalah kumpulan utas pekerja yang secara efisien menjalankan panggilan balik asinkron atas nama aplikasi. Thread pool terutama digunakan untuk mengurangi jumlah utas aplikasi dan memungkinkan pengelolaan utas pekerja. Aplikasi dapat mengantre item kerja, mengaitkan item kerja dengan handle yang bisa ditunggu, secara otomatis mengantre berdasarkan pewaktu, dan mengaitkannya dengan I/O.

Arsitektur Kumpulan Utas

Aplikasi berikut dapat memperoleh manfaat dari menggunakan kumpulan utas:

  • Aplikasi yang sangat paralel dan dapat mengirimkan sejumlah besar item kerja kecil secara asinkron (seperti pencarian indeks terdistribusi atau I/O jaringan).
  • Aplikasi yang membuat dan menghancurkan sejumlah besar utas yang masing-masing berjalan untuk waktu yang singkat. Menggunakan kumpulan utas dapat mengurangi kompleksitas manajemen utas dan overhead yang terlibat dalam pembuatan dan penghancuran utas.
  • Aplikasi yang memproses item kerja independen di latar belakang dan secara paralel (seperti memuat beberapa tab).
  • Aplikasi yang harus melakukan tunggu eksklusif pada objek kernel atau memblokir peristiwa masuk pada objek. Menggunakan kumpulan utas dapat mengurangi kompleksitas manajemen utas dan meningkatkan performa dengan mengurangi jumlah sakelar konteks.
  • Aplikasi yang membuat utas penunggu kustom untuk menunggu kejadian.

Pool thread asli telah dirancang ulang sepenuhnya di Windows Vista. Kumpulan utas baru ditingkatkan karena menyediakan jenis utas pekerja tunggal (mendukung I/O dan non-I/O), tidak menggunakan utas timer, menyediakan antrean timer tunggal, dan menyediakan utas persisten khusus. Ini juga menyediakan grup pembersihan, performa yang lebih tinggi, beberapa kumpulan per proses yang dijadwalkan secara independen, dan API kumpulan utas baru.

Arsitektur kumpulan utas terdiri atas komponen berikut:

  • Alur pekerja yang menjalankan fungsi panggilan balik
  • Utas penunggu yang menunggu beberapa objek tunggu
  • Antrean kerja
  • Pool thread bawaan untuk setiap proses
  • Pabrik pekerja yang mengelola utas pekerja

Praktik Terbaik

API kumpulan utas baru memberikan lebih banyak fleksibilitas dan kontrol daripada API kumpulan utas asli. Namun, ada beberapa perbedaan kecil namun penting. Di API asli, pengaturan ulang tunggu otomatis; di API baru, penantian harus direset secara eksplisit setiap kali. API asli menangani peniruan secara otomatis, mentransfer konteks keamanan proses panggilan ke utas. Dengan API baru, aplikasi harus secara eksplisit mengatur konteks keamanan.

Berikut adalah praktik terbaik saat menggunakan thread pool:

  • Utas-utas dalam suatu proses berbagi pool utas. Satu utas pekerja dapat menjalankan beberapa fungsi panggilan balik, secara satu per satu. Utas pekerja ini dikelola oleh kumpulan utas. Oleh karena itu, jangan menghentikan utas dari kumpulan utas dengan memanggil TerminateThread pada utas atau dengan memanggil ExitThread dari fungsi panggilan balik.

  • Permintaan I/O dapat berjalan pada utas apa pun di kumpulan utas. Membatalkan I/O pada utas kumpulan utas memerlukan sinkronisasi karena fungsi pembatalan mungkin berjalan pada utas yang berbeda dari yang menangani permintaan I/O, yang dapat mengakibatkan pembatalan operasi yang tidak diketahui. Untuk menghindari hal ini, selalu berikan struktur OVERLAPPED yang digunakan saat permintaan I/O dimulai ketika memanggil CancelIoEx untuk I/O asinkron, atau gunakan sinkronisasi Anda sendiri untuk memastikan bahwa tidak ada I/O lain yang dapat dimulai di utas target sebelum memanggil fungsi CancelSynchronousIo atau CancelIoEx.

  • Bersihkan semua sumber daya yang dibuat dalam fungsi panggilan balik sebelum kembali dari fungsi . Ini termasuk TLS, konteks keamanan, prioritas utas, dan pendaftaran COM. Fungsi callback juga harus memulihkan status thread sebelum kembali.

  • Pertahankan wait handle dan objek yang terkait dengannya tetap hidup hingga pool utas memberi sinyal bahwa pool tersebut telah selesai menggunakan handle tersebut.

  • Tandai semua utas yang sedang menunggu operasi yang memakan waktu lama (seperti pengosongan I/O atau pembersihan sumber daya) agar kumpulan utas dapat mengalokasikan utas baru alih-alih menunggu utas tersebut.

  • Sebelum membongkar DLL yang menggunakan kumpulan utas, batalkan semua item kerja, I/O, operasi tunggu, dan timer, dan tunggu hingga panggilan balik dijalankan selesai.

  • Hindari kebuntuan dengan menghilangkan dependensi antara item kerja dan antara panggilan balik, dengan memastikan panggilan balik tidak menunggu dirinya selesai, dan dengan mempertahankan prioritas utas.

  • Jangan mengantrikan terlalu banyak item terlalu cepat dalam suatu proses yang komponen lainnya menggunakan thread pool bawaan. Ada satu kumpulan utas default per proses, termasuk Svchost.exe. Secara bawaan, setiap kumpulan utas memiliki maksimal 500 utas pekerja. Pool utas berupaya membuat lebih banyak utas pekerja ketika jumlah utas pekerja dalam keadaan siap/berjalan harus lebih sedikit daripada jumlah prosesor.

  • Hindari model apartemen berulir tunggal COM, karena tidak kompatibel dengan kumpulan utas. STA membuat status thread yang dapat memengaruhi tugas berikutnya pada thread tersebut. STA umumnya berumur panjang dan memiliki afinitas utas, yang merupakan kebalikan dari kumpulan utas.

  • Buat kumpulan utas baru untuk mengontrol prioritas dan isolasi utas, membuat karakteristik kustom, dan mungkin meningkatkan responsivitas. Namun, kumpulan utas tambahan memerlukan lebih banyak sumber daya sistem (utas, memori kernel). Terlalu banyak pool meningkatkan potensi terjadinya perebutan sumber daya CPU.

  • Jika memungkinkan, gunakan objek yang dapat ditunda alih-alih mekanisme berbasis APC untuk memberi sinyal utas kumpulan utas. APC tidak bekerja seefektif mekanisme pensinyalan lainnya saat digunakan dengan utas thread pool, karena sistem mengontrol masa pakai utas thread pool, sehingga ada kemungkinan sebuah utas dihentikan sebelum notifikasi dikirimkan.

  • Gunakan ekstensi debugger kumpulan utas, !tp. Perintah ini memiliki penggunaan berikut:

    • pool alamatflag
    • obj alamatflag
    • tqueue alamatflag
    • alamat pelayan
    • alamat pekerja

    Untuk pool, waiter, dan worker, jika alamatnya nol, perintah tersebut menampilkan semua objek. Untuk waiter dan worker, jika alamat dihilangkan, utas saat ini akan di-dump. Bendera berikut didefinisikan: 0x1 (output baris tunggal), 0x2 (anggota cadangan), dan 0x4 (antrean kerja kumpulan cadangan).

Note

Alternatif modern: Untuk aplikasi C++/WinRT, kumpulan utas Windows dapat diakses melalui koroutine — digunakan co_await winrt::resume_background() untuk mengirimkan pekerjaan ke kumpulan utas, dan co_await winrt::resume_foreground(dispatcher) untuk kembali ke utas UI. Ini memberikan konkurensi terstruktur tanpa manajemen panggilan balik manual. Untuk kode C++ standar, std::async dengan kebijakan std::launch::async menawarkan paralelisme berbasis tugas yang portabel, meskipun tidak menggunakan kumpulan utas Windows secara langsung.

API Kumpulan Utas

Menggunakan Fungsi Pool Thread