Perbedaan utama, seperti yang Anda tunjukkan dalam pertanyaan Anda, adalah apakah penjadwal akan mendahului utas. Cara seorang programmer berpikir tentang berbagi struktur data atau tentang sinkronisasi antara "utas" sangat berbeda dalam sistem preemptive dan kooperatif.
Dalam sistem kooperatif (yang dikenal dengan banyak nama, kooperatif multi-tasking , multi-tasking nonpreemptive , level pengguna , benang hijau , dan serat adalah lima yang umum saat ini) programmer dijamin bahwa kode mereka akan berjalan secara atom selama mereka tidak melakukan panggilan sistem atau panggilan apa pun yield()
. Ini membuatnya sangat mudah untuk berurusan dengan struktur data yang dibagi di antara banyak serat. Kecuali jika Anda perlu membuat panggilan sistem sebagai bagian dari bagian kritis, bagian penting tidak perlu ditandai (dengan mutex lock
dan unlock
panggilan, misalnya). Jadi dalam kode seperti:
x = x + y
y = 2 * x
programmer tidak perlu khawatir bahwa serat lain dapat bekerja dengan x
dan y
variabel - variabel pada saat yang sama. x
dan y
akan diperbarui bersama secara atomik dari perspektif semua serat lainnya. Demikian pula, semua serat dapat berbagi beberapa struktur yang lebih rumit, seperti pohon dan panggilan seperti tree.insert(key, value)
tidak perlu dilindungi oleh mutex atau bagian kritis.
Sebaliknya, dalam sistem multithreading preemptive, seperti dengan thread paralel / multicore yang benar-benar, setiap kemungkinan interleaving instruksi antara thread dimungkinkan kecuali ada bagian kritis yang eksplisit. Interupsi dan preemption bisa terjadi antara dua instruksi. Dalam contoh di atas:
thread 0 thread 1
< thread 1 could read or modify x or y at this point
read x
< thread 1 could read or modify x or y at this point
read y
< thread 1 could read or modify x or y at this point
add x and y
< thread 1 could read or modify x or y at this point
write the result back into x
< thread 1 could read or modify x or y at this point
read x
< thread 1 could read or modify x or y at this point
multiply by 2
< thread 1 could read or modify x or y at this point
write the result back into y
< thread 1 could read or modify x or y at this point
Jadi, agar benar pada sistem preemptive, atau pada sistem dengan utas yang benar-benar paralel, Anda harus mengelilingi setiap bagian penting dengan semacam sinkronisasi, seperti mutex lock
di awal dan mutex unlock
di akhir.
Serat dengan demikian lebih mirip dengan pustaka i / o asinkron daripada dibandingkan dengan thread preemptive atau thread yang benar-benar paralel. Penjadwal serat dipanggil dan dapat mengganti serat selama operasi latensi panjang i / o. Ini dapat memberikan manfaat beberapa operasi i / o simultan tanpa memerlukan operasi sinkronisasi di sekitar bagian-bagian penting. Jadi, menggunakan serat dapat, mungkin, memiliki kompleksitas pemrograman yang lebih sedikit daripada benang preemptive atau benar-benar paralel, tetapi kurangnya sinkronisasi di sekitar bagian-bagian penting akan menyebabkan hasil yang merusak jika Anda mencoba menjalankan serat dengan benar secara simultan atau preemptive.