Dalam ilmu komputer , sebuah thread eksekusi adalah urutan terkecil instruksi diprogram yang dapat dikelola secara independen oleh sistem operasi scheduler . Sebuah thread adalah proses ringan . Pelaksanaan benang dan proses berbeda dari satu sistem operasi yang lain, tetapi dalam banyak kasus, thread yang terkandung di dalam proses. Beberapa benang bisa ada dalam proses yang sama dan berbagi sumber daya seperti memori , sedangkan berbeda proses tidak berbagi sumber daya tersebut. Secara khusus, benang-benang proses berbagi petunjuk yang terakhir (kode) dan konteksnya (nilai-nilai yang variabel yang referensi pada saat tertentu).
Pada prosesor tunggal, multithreading umumnya terjadi oleh time-division
multiplexing (seperti dalam multitasking ): dengan prosesor switch antara
benang yang berbeda. Ini switching konteks umumnya terjadi cukup sering bahwa
pengguna merasakan benang atau tugas sebagai berjalan pada waktu yang sama.
Pada multiprosesor atau multi-core sistem, benang dapat benar-benar bersamaan,
dengan setiap prosesor atau inti mengeksekusi thread terpisah secara bersamaan.
Banyak sistem operasi modern langsung mendukung baik waktu-iris dan
multiprosesor threading dengan scheduler proses. The kernel dari sistem operasi
memungkinkan programmer untuk memanipulasi benang melalui system call
interface. Beberapa implementasi yang disebut kernel thread, sedangkan proses
ringan (LWP) adalah jenis spesifik kernel thread yang berbagi negara dan
informasi yang sama.
Program dapat memiliki benang user-space ketika threading dengan timer,
sinyal, atau metode lain untuk menghentikan eksekusi mereka sendiri, melakukan
semacam ad-hoc waktu mengiris .
Thread berbeda dari tradisional multitasking proses sistem operasi dalam
hal:
proses biasanya independen, sedangkan benang ada sebagai subset dari
sebuah proses
proses membawa jauh lebih negara informasi dari benang, sedangkan beberapa
thread dalam proses berbagi proses negara serta memori dan lainnya sumber daya
proses memiliki terpisah ruang alamat , sedangkan benang berbagi ruang
alamat mereka
proses berinteraksi hanya melalui disediakan sistem komunikasi
antar-proses mekanisme
konteks beralih antara benang dalam proses yang sama biasanya lebih cepat
daripada konteks beralih antara proses.
Multithreading
Multi-threading adalah pemrograman meluas dan eksekusi model yang
memungkinkan beberapa thread untuk tetap eksis dalam konteks sebuah proses
tunggal. Benang ini berbagi sumber daya proses, tetapi mampu melakukan secara
mandiri. Model threaded menyediakan pengembang dengan abstraksi yang berguna
eksekusi konkuren. Namun, mungkin aplikasi yang paling menarik dari teknologi
ini bila diterapkan pada proses tunggal untuk memungkinkan eksekusi paralel
pada sistem multiprocessing.
Ini keuntungan dari program multithreaded memungkinkan untuk beroperasi
lebih cepat pada sistem komputer yang memiliki beberapa CPU , CPU dengan
beberapa core, atau melintasi sekelompok mesin - karena benang dari program
alami meminjamkan diri untuk benar-benar bersamaan eksekusi . Dalam kasus
seperti itu, programmer perlu berhati-hati untuk menghindari kondisi ras , dan
perilaku non-intuitif lainnya. Agar data yang akan dimanipulasi dengan benar,
benang akan sering perlu untuk pertemuan dalam waktu untuk memproses data dalam
urutan yang benar. Thread mungkin juga memerlukan saling eksklusif operasi
(sering diimplementasikan menggunakan Semaphore ) untuk mencegah data umum dari
yang bersamaan dimodifikasi, atau membaca sementara dalam proses modifikasi.
Penggunaan ceroboh primitif tersebut dapat menyebabkan deadlock .
Penggunaan lain multithreading, berlaku bahkan untuk sistem single-CPU,
adalah kemampuan untuk sebuah aplikasi untuk tetap responsif terhadap masukan.
Dalam program single-threaded, jika blok utama benang eksekusi pada tugas lama
berjalan, seluruh aplikasi dapat muncul untuk membekukan. Dengan memindahkan
tugas berjalan lama tersebut kepada pekerja thread yang berjalan bersamaan
dengan eksekusi thread utama, adalah mungkin untuk aplikasi tetap responsif
terhadap input pengguna ketika menjalankan tugas di latar belakang. Di sisi
lain, dalam banyak kasus multithreading bukan satu-satunya cara untuk menjaga program
responsif, dengan non-blocking I / O dan / atau sinyal Unix yang tersedia untuk
mendapatkan hasil yang sama. [1]
Sistem operasi menjadwalkan thread di salah satu dari dua cara:
Preemptive multitasking umumnya dianggap pendekatan unggul, karena memungkinkan
sistem operasi untuk menentukan kapan beralih konteks harus terjadi. Kerugian
untuk multithreading preemptive adalah bahwa sistem dapat membuat context
switch pada waktu yang tepat, menyebabkan kunci konvoi , prioritas inversi atau
efek negatif lainnya yang dapat dihindari dengan multithreading koperasi.
Multithreading Koperasi, di sisi lain, bergantung pada benang sendiri
untuk melepaskan kontrol setelah mereka berada pada titik berhenti. Hal ini
dapat menciptakan masalah jika thread sedang menunggu sumber daya untuk menjadi
tersedia.
Sampai akhir 1990-an, CPU dalam komputer desktop tidak memiliki banyak
dukungan untuk multithreading, meskipun benang masih digunakan pada komputer
tersebut karena beralih antara benang itu umumnya masih lebih cepat daripada
proses penuh konteks switch . Prosesor di embedded system , yang memiliki
persyaratan yang lebih tinggi untuk real-time perilaku, mungkin mendukung
multithreading dengan mengurangi waktu benang-switch, mungkin dengan
mengalokasikan dedicated register file untuk setiap thread bukan menyimpan /
mengembalikan register file umum. Pada akhir 1990-an, ide melaksanakan
instruksi dari beberapa thread secara simultan, yang dikenal sebagai
multithreading simultan , telah mencapai desktop dengan Intel 's Pentium 4
prosesor, di bawah nama hiper threading . Telah turun dari Intel Core dan Core
2 arsitektur, tetapi kemudian kembali instated di Core I3 , Core i5 dan i7
arsitektur.
Proses, kernel thread, thread pengguna, dan serat
Artikel utama: Proses (komputasi) dan Serat (ilmu komputer)
Sebuah proses adalah "terberat" unit penjadwalan kernel. Proses
sudah memiliki sumber daya yang dialokasikan oleh sistem operasi. Sumber daya
termasuk memori, menangani file , soket, perangkat menangani, dan jendela.
Proses tidak berbagi ruang alamat atau file sumber daya kecuali melalui metode
eksplisit seperti mewarisi menangani file atau segmen memori bersama, atau
pemetaan file yang sama dengan cara berbagi. Proses biasanya preemptively multitasked.
Suatu kernel thread adalah "ringan" unit penjadwalan kernel.
Setidaknya satu thread kernel ada dalam setiap proses. Jika beberapa thread
kernel bisa ada dalam proses, maka mereka berbagi memori yang sama dan sumber
daya berkas. Kernel thread yang preemptively multitasked jika sistem operasi
proses scheduler adalah preemptive. Kernel thread tidak sumber daya sendiri
kecuali tumpukan , salinan register termasuk program counter , dan penyimpanan
thread-lokal (jika ada). Kernel dapat menetapkan satu thread untuk
masing-masing inti logis dalam sistem (karena setiap prosesor membagi dirinya
menjadi beberapa logical core jika mendukung multithreading, atau hanya
mendukung satu inti logis per core fisik jika tidak mendukung multithreading),
dan dapat menukar benang yang bisa diblokir. Namun, benang kernel memakan waktu
lebih lama daripada benang pengguna untuk ditukarkan.
Thread kadang-kadang diimplementasikan dalam userspace perpustakaan,
sehingga disebut benang pengguna. Kernel tidak menyadari dari mereka, sehingga
mereka dikelola dan dijadwalkan di userspace . Beberapa basis implementasi
thread pengguna mereka di atas beberapa thread kernel untuk mendapatkan
keuntungan dari multi-prosesor mesin ( M: Model N ). Dalam artikel ini istilah
"benang" (tanpa kernel atau petunjuk kualifikasi) defaultnya mengacu
pada kernel thread. Benang pengguna seperti yang diterapkan oleh mesin virtual
juga disebut benang hijau . Benang Pengguna umumnya cepat untuk membuat dan
mengelola, tetapi tidak dapat memanfaatkan multithreading atau multiprocessing
dan mendapatkan diblokir jika semua yang terkait thread kernel mereka
mendapatkan diblokir bahkan jika ada beberapa thread pengguna yang siap
dijalankan.
Serat adalah unit bahkan lebih ringan dari penjadwalan yang kooperatif
dijadwalkan : serat berjalan secara eksplisit harus "menyerah" untuk
memungkinkan serat lain untuk menjalankan, yang membuat pelaksanaannya jauh
lebih mudah daripada kernel atau petunjuk benang. Sebuah serat dapat
dijadwalkan untuk berjalan di thread apapun dalam proses yang sama. Hal ini
memungkinkan aplikasi untuk mendapatkan peningkatan kinerja dengan mengelola
penjadwalan sendiri, bukan mengandalkan pada scheduler kernel (yang mungkin
tidak disetel untuk aplikasi). Lingkungan pemrograman paralel seperti OpenMP
biasanya menerapkan tugas mereka melalui serat. Terkait erat dengan serat yang
coroutines , dengan perbedaan adalah bahwa coroutines adalah membangun bahasa
tingkat, sementara serat adalah sistem tingkat membangun.
Thread dan serat isu
Concurrency dan struktur data
Thread dalam proses yang sama berbagi ruang alamat yang sama. Hal ini
memungkinkan bersamaan menjalankan kode untuk pasangan erat dan nyaman
pertukaran data tanpa overhead atau kompleksitas dari IPC . Bila dibagi antara
benang, bagaimanapun, struktur data sederhana bahkan menjadi rentan terhadap
bahaya ras jika mereka membutuhkan lebih dari satu instruksi CPU untuk
memperbarui: dua benang mungkin berakhir mencoba untuk memperbarui struktur
data pada waktu yang sama dan merasa tiba-tiba berubah di bawah kaki. Bugs yang
disebabkan oleh bahaya ras bisa sangat sulit untuk mereproduksi dan
mengisolasi.
Untuk mencegah hal ini, threading API menawarkan sinkronisasi primitif
seperti mutexes untuk mengunci struktur data terhadap akses konkuren. Pada sistem
prosesor tunggal, benang berlari ke mutex terkunci harus tidur dan karenanya
memicu context switch. Pada sistem multi-prosesor, benang mungkin bukan polling
mutex dalam spinlock . Kedua mungkin kinerja getah dan kekuatan prosesor di SMP
sistem untuk bersaing untuk bus memori, terutama jika granularity penguncian
baik-baik saja.
I / O dan penjadwalan
Benang atau serat pengguna implementasi biasanya sepenuhnya dalam
userspace . Akibatnya, konteks beralih antara benang pengguna atau serat dalam
proses yang sama ini sangat efisien karena tidak memerlukan interaksi dengan
kernel sama sekali: context switch dapat dilakukan dengan lokal menyimpan CPU
register yang digunakan oleh thread pengguna yang sedang dijalankan atau serat
dan kemudian memuat register yang dibutuhkan oleh thread pengguna atau serat
akan dieksekusi. Sejak penjadwalan terjadi di userspace, kebijakan penjadwalan
dapat lebih mudah disesuaikan dengan kebutuhan beban kerja program.
Namun, penggunaan sistem memblokir panggilan di thread user (sebagai lawan
kernel thread) atau serat dapat menjadi masalah. Jika thread pengguna atau
serat melakukan panggilan sistem yang blok, benang pengguna lain dan serat
dalam proses tidak dapat berjalan sampai kembali system call. Sebuah contoh
khas dari masalah ini adalah ketika melakukan I / O: sebagian besar program
yang ditulis untuk melakukan I / O serempak. Ketika operasi I / O dimulai,
panggilan sistem dibuat, dan tidak kembali sampai operasi I / O telah selesai.
Pada periode intervensi, seluruh proses "diblokir" oleh kernel dan
tidak dapat dijalankan, yang kelaparan thread pengguna lain dan serat dalam
proses yang sama dari mengeksekusi.
Sebuah solusi umum untuk masalah ini adalah menyediakan I / O API yang
mengimplementasikan antarmuka sinkron dengan menggunakan non-blocking I / O
internal, dan penjadwalan lain benang pengguna atau serat sementara operasi I /
O sedang berlangsung. Solusi serupa dapat disediakan untuk panggilan memblokir
sistem lainnya. Atau, program dapat ditulis untuk menghindari penggunaan
sinkron I / O atau panggilan memblokir sistem lainnya.
SunOS 4.x diimplementasikan " proses ringan "atau LWPs. NetBSD
2.x +, dan DragonFly BSD menerapkan LWPs sebagai thread kernel (Model 1:1).
SunOS 5.2 melalui SunOS 5.8 serta NetBSD NetBSD 2 sampai 4 menerapkan model
tingkat dua, multiplexing satu atau lebih benang level pengguna pada setiap
thread kernel (M: Model N). SunOS 5.9 dan kemudian, serta NetBSD 5 dieliminasi
pengguna dukungan benang, kembali ke model 1:1. [1] FreeBSD 5 diimplementasikan
M: Model N. FreeBSD 6 mendukung kedua 1:1 dan M: N, pengguna bisa memilih mana
yang harus digunakan dengan program yang diberikan dengan menggunakan / etc /
libmap.conf. Dimulai dengan FreeBSD 7, 1:1 menjadi default. FreeBSD 8 tidak
lagi mendukung M: Model N.
Penggunaan benang kernel menyederhanakan kode pengguna dengan memindahkan
beberapa aspek yang paling kompleks threading ke dalam kernel. Program ini
tidak perlu menjadwalkan benang atau eksplisit menghasilkan prosesor. Kode
pengguna dapat ditulis dalam gaya prosedural akrab, termasuk panggilan untuk
memblokir API, tanpa kelaparan benang lain. Namun, kernel threading mungkin
memaksa konteks beralih antara benang setiap saat, dan dengan demikian
mengekspos bahaya ras dan concurrency bug yang dinyatakan akan berbohong laten.
Pada sistem SMP, ini lebih diperparah karena kernel thread dapat harfiah
mengeksekusi secara bersamaan pada prosesor yang terpisah.
Model
01:01 (Kernel-level threading)
Thread yang dibuat oleh pengguna dalam korespondensi 1-1 dengan entitas
schedulable di kernel. Ini adalah sederhana kemungkinan pelaksanaan threading.
Win32 menggunakan pendekatan ini dari awal. Pada Linux , yang C library yang
biasa menerapkan pendekatan ini (melalui NPTL atau lebih LinuxThreads ).
Pendekatan yang sama digunakan oleh Solaris , NetBSD dan FreeBSD .
[ sunting ]N: 1 (User-level threading)
Sebuah N: 1 Model menyiratkan bahwa semua benang level aplikasi peta ke
level kernel dijadwalkan entitas tunggal, kernel tidak memiliki pengetahuan
tentang benang aplikasi. Dengan pendekatan ini, switching konteks dapat
dilakukan dengan sangat cepat dan, di samping itu dapat diimplementasikan
bahkan pada kernel sederhana yang tidak mendukung threading. Salah satu
kelemahan utama bagaimanapun adalah bahwa ia tidak bisa mendapatkan keuntungan
dari akselerasi hardware pada multi-threaded prosesor atau multi-prosesor
komputer: tidak pernah lebih dari satu thread yang dijadwalkan pada waktu yang
sama. Misalnya: Jika salah satu benang perlu mengeksekusi permintaan I / O,
seluruh proses akan diblokir dan keuntungan threading tidak dapat dimanfaatkan.
The GNU Portabel Thread menggunakan User-level threading, seperti halnya Thread
Negara .
M: N (Hybrid threading)
M: N peta beberapa nomor M benang aplikasi ke beberapa nomor N entitas
kernel, atau "prosesor virtual." Ini adalah kompromi antara
kernel-level ("01:01") dan user-level ("N: 1") threading.
Secara umum, "M: N" sistem threading lebih kompleks untuk diterapkan
daripada baik kernel atau benang pengguna, karena perubahan baik kernel dan
kode user-space yang diperlukan. Dalam M: N pelaksanaan, perpustakaan threading
bertanggung jawab untuk penjadwalan thread pengguna pada entitas schedulable
tersedia, ini membuat konteks switching benang yang sangat cepat, karena
menghindari panggilan sistem. Namun, ini meningkatkan kompleksitas dan
kemungkinan inversi prioritas , serta penjadwalan suboptimal tanpa ekstensif
(dan mahal) koordinasi antara scheduler userland dan scheduler kernel.
contoh implementasi Hybrid
Scheduler aktivasi yang digunakan oleh NetBSD asli POSIX thread
implementasi perpustakaan (sebuah M: Model N sebagai lawan kernel 1:1 atau
model implementasi userspace)
Marcel dari PM2 proyek.
OS untuk Tera / Cray MTA
Microsoft Windows 7
contoh implementasi Fiber
Serat dapat dilaksanakan tanpa dukungan sistem operasi, meskipun beberapa
sistem operasi atau perpustakaan memberikan dukungan eksplisit untuk mereka.
Win32 API memasok serat [3] (Windows NT 3.51 SP3 dan kemudian)
Ruby sebagai benang Hijau
Netscape Portabel Runtime (termasuk implementasi serat user-space)
Pemrograman dukungan bahasa
Banyak bahasa pemrograman mendukung threading dalam beberapa kapasitas.
Banyak implementasi dari C dan C + + memberikan dukungan untuk threading
sendiri, tetapi juga memberikan akses ke threading API asli yang disediakan
oleh sistem operasi. Beberapa tingkat yang lebih tinggi (dan biasanya lintas
platform) bahasa pemrograman seperti Java, Python, dan NET., Mengekspos
threading untuk pengembang sedangkan abstrak perbedaan spesifik platform dalam
implementasi threading di runtime untuk pengembang. Sejumlah bahasa pemrograman
lain juga mencoba abstrak konsep concurrency dan threading dari pengembang sama
sekali ( Cilk , OpenMP , MPI ). Beberapa bahasa yang dirancang untuk
paralelisme (Ateji PX, CUDA ).
Beberapa bahasa pemrograman ditafsirkan seperti Ruby dan (pelaksanaan
CPython dari) Python dukungan threading, tetapi memiliki keterbatasan yang
dikenal sebagai Juru Kunci global (GIL). GIL merupakan kunci saling
pengecualian diselenggarakan oleh interpreter yang dapat mencegah penafsir dari
bersamaan menafsirkan aplikasi kode pada dua atau lebih benang pada saat yang
sama, yang secara efektif membatasi concurrency pada beberapa sistem inti
(sebagian besar untuk benang prosesor-terikat, dan tidak banyak untuk yang
network-bound).
Pemrograman event-driven bahasa deskripsi hardware seperti Verilog
memiliki model threading berbeda yang mendukung sangat besar jumlah benang (untuk
modeling hardware).