Apa arti dari istilah "aman-aman"?

367

Apakah ini berarti bahwa dua utas tidak dapat mengubah data yang mendasarinya secara bersamaan? Atau apakah itu berarti bahwa segmen kode yang diberikan akan berjalan dengan hasil yang dapat diprediksi ketika beberapa utas mengeksekusi segmen kode itu?

Varun Mahajan
sumber
8
Baru saja melihat diskusi yang menarik di sini tentang masalah ini: blogs.msdn.com/ericlippert/archive/2009/10/19/…
Sebastian

Jawaban:

256

Dari Wikipedia:

Thread safety adalah konsep pemrograman komputer yang berlaku dalam konteks program multi-threaded. Sepotong kode aman untuk thread jika berfungsi dengan benar selama eksekusi simultan oleh beberapa utas. Khususnya, ia harus memenuhi kebutuhan akan banyak utas untuk mengakses data bersama yang sama, dan perlunya sepotong data bersama untuk diakses oleh hanya satu utas pada waktu tertentu.

Ada beberapa cara untuk mencapai keamanan benang:

Re-entrancy:

Menulis kode sedemikian rupa sehingga sebagian dapat dieksekusi oleh satu tugas, dimasukkan kembali oleh tugas lain, dan kemudian dilanjutkan dari tugas aslinya. Ini memerlukan penghematan informasi status dalam variabel lokal untuk setiap tugas, biasanya pada stack-nya, bukan dalam variabel statis atau global.

Pengucilan bersama:

Akses ke data bersama diserialisasi menggunakan mekanisme yang memastikan hanya satu utas membaca atau menulis data bersama kapan saja. Diperlukan kehati-hatian jika sepotong kode mengakses beberapa bagian data yang dibagi — masalah termasuk kondisi ras, kebuntuan, livelock, kelaparan, dan berbagai penyakit lain yang disebutkan dalam banyak buku teks sistem operasi.

Penyimpanan thread-lokal:

Variabel dilokalkan sehingga setiap utas memiliki salinan pribadi masing-masing. Variabel-variabel ini mempertahankan nilainya melintasi subrutin dan batas kode lainnya, dan aman untuk thread karena bersifat lokal untuk setiap utas, meskipun kode yang mengaksesnya mungkin reentrant.

Operasi atom:

Data bersama diakses dengan menggunakan operasi atom yang tidak dapat diinterupsi oleh utas lainnya. Ini biasanya memerlukan menggunakan instruksi bahasa mesin khusus, yang mungkin tersedia di perpustakaan runtime. Karena operasi bersifat atomik, data yang dibagikan selalu disimpan dalam keadaan valid, tidak peduli apa pun thread lain yang mengaksesnya. Operasi atom membentuk dasar dari banyak mekanisme penguncian ulir.

Baca lebih banyak:

http://en.wikipedia.org/wiki/Thread_safety


Blauohr
sumber
4
Tautan ini, secara teknis, kehilangan beberapa titik kritis. Memori bersama yang dipertanyakan harus dapat diubah, (Memori hanya-baca tidak boleh menjadi thread-Tidak Aman), dan beberapa utas harus, a) melakukan beberapa operasi penulisan pada memori selama bagian tengah memori tidak konsisten (salah) nyatakan, dan b) biarkan utas lain menginterupsi utas itu sementara memori tidak konsisten.
Charles Bretana
20
ketika mencari Google hasil pertama adalah wiki, tidak ada gunanya membuatnya berlebihan di sini.
Ranvir
Apa maksud Anda "kode yang mengakses suatu fungsi"? Fungsi yang dieksekusi sendiri adalah kode, bukan?
Koray Tugay
82

Kode thread-aman adalah kode yang akan berfungsi bahkan jika banyak Thread mengeksekusi secara bersamaan.

http://mindprod.com/jgloss/threadsafe.html

Marek Blotny
sumber
34
Dalam proses yang sama!
Ali Afshar
Memang, dalam proses yang sama :)
Marek Blotny
4
"Untuk menulis kode yang akan berjalan stabil selama berminggu-minggu membutuhkan paranoia ekstrem." Itu kutipan yang saya suka :)
Jim T
5
ya! jawaban ini hanya menyatakan kembali pertanyaan! --- Dan mengapa hanya dalam proses yang sama ??? Jika kode gagal ketika beberapa utas menjalankannya dari proses yang berbeda, maka, bisa dibilang, ("memori bersama" mungkin ada dalam file disk), itu BUKAN utas aman !!
Charles Bretana
1
@ mg30rg. Mungkin kebingungan adalah hasil dari entah bagaimana berpikir bahwa ketika satu blok kode dieksekusi oleh banyak proses, tetapi hanya dengan satu utas per proses, bahwa itu, entah bagaimana masih merupakan skenario "Utas tunggal", bukan skenario utas ganda . Gagasan ini bahkan tidak salah. Itu hanya salah definisi. Jelas, banyak proses biasanya tidak dieksekusi pada utas yang sama secara tersinkronisasi, (kecuali dalam skenario langka di mana proses dengan desain berkoordinasi satu sama lain dan OS berbagi utas di antara proses.)
Charles Bretana
50

Pertanyaan yang lebih informatif adalah apa yang membuat kode bukan utas aman- dan jawabannya adalah bahwa ada empat syarat yang harus benar ... Bayangkan kode berikut (dan ini terjemahan bahasa mesin)

totalRequests = totalRequests + 1
MOV EAX, [totalRequests]   // load memory for tot Requests into register
INC EAX                    // update register
MOV [totalRequests], EAX   // store updated value back to memory
  1. Kondisi pertama adalah bahwa ada lokasi memori yang dapat diakses dari lebih dari satu utas. Biasanya, lokasi-lokasi ini adalah variabel global / statis atau memori tumpukan dapat dicapai dari variabel global / statis. Setiap utas mendapatkan bingkai tumpukan sendiri untuk variabel lokal fungsi / metode yang mencakup, jadi variabel fungsi / metode lokal ini, otoh, (yang ada di tumpukan) hanya dapat diakses dari satu utas yang memiliki tumpukan itu.
  2. Kondisi kedua adalah bahwa ada properti (sering disebut invarian ), yang dikaitkan dengan lokasi memori bersama ini, yang harus benar, atau valid, agar program berfungsi dengan benar. Dalam contoh di atas, propertinya adalah “ totalRequests harus secara akurat menunjukkan jumlah total setiap utas yang telah menjalankan bagian mana pun dari pernyataan kenaikan ”. Biasanya, properti invarian ini harus benar (dalam kasus ini, totalRequests harus memiliki jumlah yang akurat) sebelum pembaruan terjadi agar pembaruan benar.
  3. Kondisi ketiga adalah bahwa properti invarian TIDAK tahan selama beberapa bagian dari pembaruan aktual. (Ini sementara tidak valid atau salah selama beberapa bagian dari pemrosesan). Dalam kasus khusus ini, dari saat totalRequests diambil hingga saat nilai yang diperbarui disimpan, totalRequests tidak memuaskan yang invarian.
  4. Kondisi keempat dan terakhir yang harus terjadi untuk sebuah perlombaan terjadi (dan agar kode BUKAN menjadi "thread-safe") adalah bahwa utas lain harus dapat mengakses memori bersama sementara invarian rusak, sehingga menyebabkan tidak konsisten atau perilaku yang salah.
Charles Bretana
sumber
6
Ini hanya mencakup apa yang dikenal sebagai ras data , dan tentu saja penting. Namun, ada cara lain bagaimana kode tidak dapat diamankan - misalnya penguncian buruk yang dapat menyebabkan kebuntuan. Bahkan sesuatu yang sederhana seperti memanggil System.exit () di suatu tempat di thread java membuat kode itu tidak aman.
Ingo
2
Saya kira pada tingkat tertentu ini adalah semantik, tapi saya berpendapat bahwa kode penguncian yang buruk yang dapat menyebabkan kebuntuan tidak membuat kode tidak aman. Pertama, tidak perlu mengunci kode di tempat pertama kecuali kondisi balapan, seperti yang dijelaskan di atas, adalah mungkin. Kemudian, jika Anda menulis kode penguncian sedemikian rupa sehingga menyebabkan kebuntuan, itu bukan thread-tidak aman, itu hanya kode yang buruk.
Charles Bretana
1
Tetapi perhatikan bahwa kebuntuan tidak akan terjadi ketika menjalankan single-threaded, jadi bagi sebagian besar dari kita ini pasti akan jatuh di bawah makna intuitif "tidak aman".
Jon Coombs
Kebuntuan tidak dapat terjadi kecuali Anda menjalankan multi-threaded tentu saja, Tapi itu seperti mengatakan masalah jaringan tidak dapat terjadi jika Anda menjalankan pada satu mesin. Masalah lain dapat terjadi single-threaded juga, jika programmer menulis kode sehingga keluar dari garis kritis kode sebelum menyelesaikan pembaruan, dan memodifikasi variabel dalam beberapa subrutin lainnya.
Charles Bretana
34

Saya menyukai definisi Java Concurrency in Practice dari Brian Goetz untuk kelengkapannya

"Kelas adalah thread-safe jika berperilaku dengan benar ketika diakses dari beberapa utas, terlepas dari penjadwalan atau interleaving dari pelaksanaan utas tersebut oleh lingkungan runtime, dan tanpa sinkronisasi tambahan atau koordinasi lainnya pada bagian dari kode panggilan. "

Buu Nguyen
sumber
Definisi ini tidak lengkap dan tidak spesifik, dan jelas tidak komprehensif. Berapa kali harus berjalan dengan aman, Sekali saja? sepuluh kali? setiap saat? 80% dari waktu? dan itu tidak menentukan apa yang membuatnya "Tidak Aman". Jika gagal berjalan dengan aman, tetapi kegagalan itu karena ada kesalahan dengan pembagian nol, apakah itu membuatnya thread- "Tidak Aman"?
Charles Bretana
Lebih sopan lagi lain kali dan mungkin kita bisa berdiskusi. Ini bukan Reddit dan aku sedang tidak ingin berbicara dengan orang yang kasar.
Buu Nguyen
Komentar interpretasi Anda tentang definisi orang lain sebagai penghinaan terhadap diri Anda sendiri sudah jelas. Anda perlu membaca dan memahami substansi sebelum bereaksi secara emosional. Tidak ada yang tidak sopan tentang komentar saya. Saya membuat poin tentang arti definisi tersebut. Maaf jika contoh yang saya gunakan untuk menggambarkan hal ini membuat Anda tidak nyaman.
Charles Bretana
28

Seperti yang telah ditunjukkan oleh orang lain, keamanan utas berarti bahwa sepotong kode akan berfungsi tanpa kesalahan jika digunakan oleh lebih dari satu utas sekaligus.

Perlu disadari bahwa ini kadang-kadang terjadi pada biaya, waktu komputer dan pengkodean yang lebih kompleks, sehingga tidak selalu diinginkan. Jika suatu kelas dapat digunakan dengan aman hanya pada satu utas, mungkin lebih baik melakukannya.

Sebagai contoh, Java memiliki dua kelas yang hampir setara, StringBufferdan StringBuilder. Perbedaannya adalah StringBufferthread-safe, jadi instance tunggal dari StringBufferdapat digunakan oleh banyak utas sekaligus. StringBuilderbukan thread-safe, dan dirancang sebagai pengganti berkinerja tinggi untuk kasus-kasus tersebut (sebagian besar) ketika String dibangun hanya oleh satu utas.

Marcus Downing
sumber
22

Thread-safe-code berfungsi seperti yang ditentukan, bahkan ketika dimasukkan secara bersamaan oleh utas berbeda. Ini sering berarti, bahwa struktur data internal atau operasi yang harus dijalankan tanpa gangguan dilindungi terhadap modifikasi yang berbeda pada saat yang sama.

Mnementh
sumber
21

Cara yang lebih mudah untuk memahaminya, adalah apa yang membuat kode tidak aman. Ada dua masalah utama yang akan membuat aplikasi berulir memiliki perilaku yang tidak diinginkan.

  • Mengakses variabel bersama tanpa mengunci
    Variabel ini dapat dimodifikasi oleh utas lainnya saat menjalankan fungsi. Anda ingin mencegahnya dengan mekanisme penguncian untuk memastikan perilaku fungsi Anda. Aturan umum adalah untuk menjaga kunci untuk waktu sesingkat mungkin.

  • Jalan buntu yang disebabkan oleh saling ketergantungan pada variabel bersama.
    Jika Anda memiliki dua variabel bersama A dan B. Dalam satu fungsi, Anda mengunci A terlebih dahulu kemudian Anda mengunci B. Dalam fungsi lain, Anda mulai mengunci B dan setelah beberapa saat, Anda mengunci A. Ini adalah kebuntuan potensial di mana fungsi pertama akan menunggu B untuk dibuka ketika fungsi kedua akan menunggu A dibuka. Masalah ini mungkin tidak akan terjadi di lingkungan pengembangan Anda dan hanya dari waktu ke waktu. Untuk menghindarinya, semua kunci harus selalu dalam urutan yang sama.

Hapkido
sumber
9

Iya dan tidak.

Keamanan utas sedikit lebih dari sekadar memastikan data Anda yang dibagikan diakses hanya oleh satu utas sekaligus. Anda harus memastikan akses berurutan ke data bersama, sementara pada saat yang sama menghindari kondisi balapan , kebuntuan , penghidupan , dan kelaparan sumber daya .

Hasil yang tidak dapat diprediksi saat beberapa utas berjalan bukanlah kondisi yang diperlukan dari kode aman-ulir, tetapi sering merupakan produk sampingan. Misalnya, Anda dapat mengatur skema produsen-konsumen dengan antrian bersama, satu utas produsen, dan beberapa utas konsumen, dan aliran data mungkin dapat diprediksi dengan sempurna. Jika Anda mulai memperkenalkan lebih banyak konsumen, Anda akan melihat hasil yang terlihat lebih acak.

Bill the Lizard
sumber
9

Pada dasarnya, banyak hal bisa salah dalam lingkungan multi-ulir (instruksi menata ulang, objek yang dibangun sebagian, variabel yang sama memiliki nilai yang berbeda di utas yang berbeda karena caching di level CPU dll.).

Saya suka definisi yang diberikan oleh Java Concurrency in Practice :

[Bagian kode] aman-thread jika berperilaku dengan benar ketika diakses dari beberapa utas, terlepas dari penjadwalan atau interleaving dari pelaksanaan utas tersebut oleh lingkungan runtime, dan tanpa sinkronisasi tambahan atau koordinasi lain pada bagian dari kode panggilan.

Yang mereka maksud dengan benar adalah program berperilaku sesuai dengan spesifikasinya.

Contoh buatan

Bayangkan Anda menerapkan penghitung. Anda dapat mengatakan bahwa itu berlaku dengan benar jika:

  • counter.next() jangan pernah mengembalikan nilai yang telah dikembalikan sebelumnya (kami menganggap tidak ada luapan, dll. untuk kesederhanaan)
  • semua nilai dari 0 hingga nilai saat ini telah dikembalikan pada tahap tertentu (tidak ada nilai yang dilompati)

Penghitung thread aman akan berperilaku sesuai dengan aturan itu terlepas dari berapa banyak thread mengaksesnya secara bersamaan (yang biasanya tidak akan menjadi kasus implementasi yang naif).

Catatan: lintas pos pada Programmer

assylias
sumber
8

Cukup - kode akan berjalan dengan baik jika banyak utas yang mengeksekusi kode ini secara bersamaan.

Greg Balajewicz
sumber
5

Jangan bingung keselamatan thread dengan determinisme. Kode thread-safe juga bisa non-deterministik. Mengingat sulitnya masalah debugging dengan kode berulir, ini mungkin merupakan kasus normal. :-)

Keamanan utas hanya memastikan bahwa ketika utas memodifikasi atau membaca data yang dibagikan, tidak ada utas lain yang dapat mengaksesnya dengan cara yang mengubah data. Jika kode Anda bergantung pada urutan tertentu untuk eksekusi demi kebenaran, maka Anda memerlukan mekanisme sinkronisasi lain selain yang diperlukan untuk keamanan utas untuk memastikan hal ini.

tvanfosson
sumber
5

Saya ingin menambahkan lebih banyak info di atas jawaban baik lainnya.

Keamanan thread menyiratkan beberapa utas dapat menulis / membaca data dalam objek yang sama tanpa kesalahan memori yang tidak konsisten. Dalam program yang sangat multi-threaded, program yang aman thread tidak menyebabkan efek samping untuk data bersama .

Lihat pertanyaan SE ini untuk lebih jelasnya:

Apa maksud dari threadsafe?

Program thread aman menjamin konsistensi memori .

Dari halaman dokumentasi oracle pada API bersamaan lanjutan:

Properti Konsistensi Memori:

Bab 17 dari Spesifikasi Bahasa Java ™ mendefinisikan hubungan yang terjadi sebelum operasi memori seperti membaca dan menulis variabel bersama. Hasil penulisan oleh satu utas dijamin akan terlihat oleh pembacaan oleh utas lain hanya jika operasi penulisan terjadi sebelum operasi baca .

The synchronizeddan volatilekonstruksi, serta Thread.start()dan Thread.join()metode, bentuk kaleng terjadi-sebelum hubungan.

Metode semua kelas di dalam java.util.concurrentdan sub paketnya memperpanjang jaminan ini untuk sinkronisasi tingkat yang lebih tinggi. Khususnya:

  1. Tindakan di utas sebelum menempatkan objek ke dalam kumpulan konkursi apa pun terjadi sebelum tindakan setelah akses atau penghapusan elemen itu dari koleksi di utas lain.
  2. Tindakan di utas sebelum pengajuan a Runnableke yang Executorterjadi sebelum eksekusi dimulai. Demikian pula untuk Callable yang dikirimkan ke ExecutorService.
  3. Tindakan yang diambil oleh perhitungan asinkron diwakili oleh Futuretindakan sebelum terjadi setelah pengambilan hasil melalui Future.get()di utas lainnya.
  4. Tindakan sebelum "melepaskan" metode sinkronisasi seperti Lock.unlock, Semaphore.release, and CountDownLatch.countDowntindakan yang terjadi sebelum tindakan yang berhasil "memperoleh" metode seperti Lock.lock, Semaphore.acquire, Condition.await, and CountDownLatch.awaitpada objek sinkronisasi yang sama di utas lain.
  5. Untuk setiap pasangan utas yang berhasil bertukar objek melalui Exchanger, tindakan sebelum di exchange()dalam setiap utas terjadi sebelum sebelum yang terkait dengan pertukaran yang sesuai () di utas lain.
  6. Tindakan sebelum pemanggilan CyclicBarrier.awaitdan Phaser.awaitAdvance(serta variannya) terjadi-sebelum tindakan dilakukan oleh tindakan penghalang, dan tindakan yang dilakukan oleh tindakan penghalang terjadi-sebelum tindakan setelah pengembalian yang berhasil dari yang sesuai menunggu di utas lainnya.
Ravindra babu
sumber
4

Untuk melengkapi jawaban lain:

Sinkronisasi hanya khawatir ketika kode dalam metode Anda melakukan satu dari dua hal:

  1. bekerja dengan beberapa sumber luar yang tidak aman utas.
  2. Membaca atau mengubah objek objek atau kelas yang persisten

Ini berarti bahwa variabel yang didefinisikan dalam metode Anda selalu aman. Setiap panggilan ke suatu metode memiliki versi variabel-variabel ini sendiri. Jika metode ini dipanggil oleh utas lain, atau oleh utas yang sama, atau bahkan jika metode itu menyebut dirinya sendiri (rekursi), nilai-nilai variabel ini tidak dibagi.

Penjadwalan utas tidak dijamin bulat-robin . Suatu tugas dapat sepenuhnya memakan CPU dengan mengorbankan utas dengan prioritas yang sama. Anda dapat menggunakan Thread.yield () untuk memiliki hati nurani. Anda dapat menggunakan (dalam java) Thread.setPriority (Thread.NORM_PRIORITY-1) untuk menurunkan prioritas utas

Selain itu waspadai:

  • biaya runtime yang besar (sudah disebutkan oleh orang lain) pada aplikasi yang beralih pada struktur "thread-safe" ini.
  • Thread.sleep (5000) seharusnya tidur selama 5 detik. Namun, jika seseorang mengubah waktu sistem, Anda dapat tidur untuk waktu yang sangat lama atau tidak ada waktu sama sekali. OS merekam waktu bangun dalam bentuk absolut, bukan relatif.
VONC
sumber
2

Ya dan ya. Ini menyiratkan bahwa data tidak dimodifikasi oleh lebih dari satu utas secara bersamaan. Namun, program Anda mungkin berfungsi seperti yang diharapkan, dan tampaknya aman, meskipun pada dasarnya tidak.

Perhatikan bahwa hasil yang tidak dapat diprediksi adalah konsekuensi dari 'kondisi ras' yang mungkin menghasilkan data yang dimodifikasi dalam urutan selain yang diharapkan.

Steve Knight
sumber
2

Mari kita jawab ini dengan contoh:

class NonThreadSafe {

    private int counter = 0;

    public boolean countTo10() {
        count = count + 1;
        return (count == 10);
    }

The countTo10Metode menambahkan satu ke meja dan kemudian mengembalikan nilai true jika count telah mencapai 10. Ini hanya harus kembali sekali benar.

Ini akan berfungsi selama hanya satu utas yang menjalankan kode. Jika dua utas menjalankan kode pada saat yang sama berbagai masalah dapat terjadi.

Misalnya, jika hitungan dimulai sebagai 9, satu utas dapat menambahkan 1 untuk dihitung (menghasilkan 10) tetapi kemudian utas kedua dapat memasukkan metode dan menambahkan 1 lagi (membuat 11) sebelum utas pertama memiliki kesempatan untuk melakukan perbandingan dengan 10 Kemudian kedua utas melakukan perbandingan dan menemukan bahwa hitung adalah 11 dan tidak ada yang mengembalikan true.

Jadi kode ini bukan utas yang aman.

Intinya, semua masalah multi-threading disebabkan oleh beberapa variasi masalah semacam ini.

Solusinya adalah memastikan bahwa penambahan dan perbandingan tidak dapat dipisahkan (misalnya dengan mengelilingi kedua pernyataan dengan semacam kode sinkronisasi) atau dengan menyusun solusi yang tidak memerlukan dua operasi. Kode seperti itu akan aman-thread.

rghome
sumber
1

Setidaknya di C ++, saya menganggap thread-safe sebagai sedikit keliru karena meninggalkan banyak nama. Agar aman utas, kode biasanya harus proaktif tentangnya. Ini umumnya bukan kualitas pasif.

Agar suatu kelas aman dari tapak, ia harus memiliki fitur "ekstra" yang menambahkan overhead. Fitur-fitur ini adalah bagian dari implementasi kelas dan secara umum, tersembunyi dari antarmuka. Yaitu, utas berbeda dapat mengakses anggota kelas mana pun tanpa harus khawatir tentang pertentangan dengan akses bersamaan oleh utas berbeda DAN dapat melakukannya dengan cara yang sangat malas, menggunakan gaya pengkodean manusia biasa yang biasa, tanpa harus melakukan semua hal sinkronisasi gila yang sudah dimasukkan ke dalam isi kode yang dipanggil.

Dan inilah mengapa sebagian orang lebih suka menggunakan istilah yang disinkronkan secara internal .

Set Terminologi

Ada tiga set terminologi utama untuk ide-ide ini yang saya temui. Yang pertama dan secara historis lebih populer (tetapi lebih buruk) adalah:

  1. benang aman
  2. bukan utas yang aman

Yang kedua (dan lebih baik) adalah:

  1. bukti utas
  2. thread yang kompatibel
  3. utas permusuhan

Yang ketiga adalah:

  1. disinkronkan secara internal
  2. disinkronkan secara eksternal
  3. tidak dapat disinkronkan

Analogi

utas aman ~ utas bukti ~ disinkronkan secara internal

Contoh dari sistem yang disinkronkan secara internal (alias thread-safe atau thread proof ) adalah restoran tempat tuan rumah menyambut Anda di pintu, dan melarang Anda mengantri. Tuan rumah adalah bagian dari mekanisme restoran untuk berurusan dengan banyak pelanggan, dan dapat menggunakan beberapa trik yang agak rumit untuk mengoptimalkan tempat duduk pelanggan yang menunggu, seperti mempertimbangkan ukuran pesta mereka, atau berapa banyak waktu yang mereka miliki. , atau bahkan mengambil reservasi melalui telepon. Restoran disinkronkan secara internal karena semua ini adalah bagian dari antarmuka untuk berinteraksi dengannya.

bukan thread-safe (tapi bagus) ~ thread yang kompatibel ~ disinkronkan secara eksternal ~ free-threaded

Misalkan Anda pergi ke bank. Ada garis, yaitu pertentangan untuk teller bank. Karena Anda bukan orang biadab, Anda menyadari bahwa hal terbaik yang harus dilakukan di tengah pertengkaran untuk sumber daya adalah mengantri seperti makhluk beradab. Tidak ada yang secara teknis membuat Anda melakukan ini. Kami harap Anda memiliki pemrograman sosial yang diperlukan untuk melakukannya sendiri. Dalam hal ini, lobi bank disinkronkan secara eksternal. Haruskah kita mengatakan bahwa itu tidak aman? itulah yang implikasinya adalah jika Anda pergi dengan benang-aman , benang-aman bipolar set terminologi. Itu bukan istilah yang sangat baik. Terminologi yang lebih baik disinkronkan secara eksternal,Lobi bank tidak mudah diakses oleh banyak pelanggan, tetapi tidak melakukan sinkronisasi dengan mereka. Pelanggan melakukannya sendiri.

Ini juga disebut "utas gratis," di mana "bebas" seperti dalam "bebas dari kutu" - atau dalam hal ini, terkunci. Nah, lebih tepatnya, sinkronisasi primitif. Itu tidak berarti kode dapat berjalan di banyak utas tanpa primitif itu. Itu hanya berarti itu tidak datang dengan mereka sudah diinstal dan terserah Anda, pengguna kode, untuk menginstalnya sendiri sesuai keinginan Anda. Memasang primitif sinkronisasi Anda sendiri bisa jadi sulit dan membutuhkan pemikiran keras tentang kode, tetapi juga dapat mengarah pada program tercepat yang memungkinkan dengan menyesuaikan Anda dengan bagaimana program dijalankan pada CPU yang saat ini diretas.

bukan utas aman (dan buruk) ~ utas permusuhan ~ tidak dapat disinkronkan

Contoh analogi sehari-hari dari sistem benang-bermusuhan adalah beberapa brengsek dengan mobil sport yang menolak untuk menggunakan penutup mata mereka dan mengubah jalur mau tak mau. Gaya mengemudi mereka tidak bersahabat atau tidak dapat dipahami karena Anda tidak memiliki cara untuk berkoordinasi dengan mereka, dan ini dapat menyebabkan pertengkaran untuk jalur yang sama, tanpa resolusi, dan dengan demikian kecelakaan ketika dua mobil berusaha untuk menempati ruang yang sama, tanpa protokol apa pun untuk cegah ini. Pola ini juga dapat dianggap lebih luas sebagai anti-sosial, yang saya sukai karena kurang spesifik untuk utas dan lebih umum berlaku untuk banyak bidang pemrograman.

Mengapa thread safe et al. adalah set terminologi yang buruk

Set terminologi pertama dan tertua gagal membuat perbedaan yang lebih baik antara permusuhan thread dan kompatibilitas thread . Kompatibilitas thread lebih pasif daripada yang disebut safety thread, tetapi itu tidak berarti kode yang dipanggil tidak aman untuk penggunaan thread bersamaan. Itu hanya berarti pasif tentang sinkronisasi yang akan memungkinkan ini, menundanya ke kode panggilan, alih-alih menyediakannya sebagai bagian dari implementasi internal. Thread kompatibel adalah bagaimana kode mungkin harus ditulis secara default dalam banyak kasus, tetapi sayangnya ini juga sering keliru dianggap sebagai thread tidak aman, seolah-olah itu inheren anti keselamatan, yang merupakan titik utama kebingungan bagi para programmer.

CATATAN: Banyak manual perangkat lunak yang benar-benar menggunakan istilah "thread-safe" untuk merujuk pada "thread-kompatibel," menambahkan lebih banyak kebingungan pada apa yang sudah berantakan! Saya menghindari istilah "thread-safe" dan "thread-safe" di semua biaya karena alasan ini, karena beberapa sumber akan menyebut sesuatu "thread-safe" sementara yang lain akan menyebutnya "thread-safe" karena mereka tidak dapat setuju apakah Anda harus memenuhi beberapa standar ekstra untuk keselamatan (primitif sinkronisasi), atau TIDAK memusuhi dianggap "aman". Jadi hindari istilah-istilah itu dan gunakan istilah yang lebih cerdas, untuk menghindari miskomunikasi berbahaya dengan insinyur lain.

Pengingat tujuan kami

Pada dasarnya, tujuan kami adalah untuk menumbangkan kekacauan.

Kami melakukannya dengan menciptakan sistem deterministik yang dapat kami andalkan. Determinisme itu mahal, sebagian besar karena biaya peluang kehilangan paralelisme, pipelining, dan pemesanan ulang. Kami mencoba meminimalkan jumlah determinisme yang kami butuhkan untuk menjaga biaya tetap rendah, sambil menghindari pengambilan keputusan yang akan mengikis lebih sedikit determinisme yang kami mampu.

Sinkronisasi utas adalah tentang meningkatkan urutan dan mengurangi kekacauan. Tingkat di mana Anda melakukan ini sesuai dengan persyaratan yang disebutkan di atas. Level tertinggi berarti bahwa suatu sistem berperilaku dengan cara yang sepenuhnya dapat diprediksi setiap saat. Tingkat kedua berarti bahwa sistem berperilaku cukup baik sehingga kode panggilan dapat dengan andal mendeteksi ketidakpastian. Misalnya, bangun palsu dalam kondisi variabel atau kegagalan untuk mengunci mutex karena tidak siap. Tingkat ketiga berarti bahwa sistem tidak berperilaku cukup baik untuk bermain dengan orang lain dan hanya bisa PERNAH dijalankan dengan single-threaded tanpa menimbulkan kekacauan.

Daniel Russell
sumber
1

Alih-alih menganggap kode atau kelas sebagai thread aman atau tidak, saya pikir lebih bermanfaat untuk menganggap tindakan sebagai thread-safe. Dua tindakan aman thread jika mereka akan berperilaku seperti yang ditentukan saat dijalankan dari konteks threading sewenang-wenang. Dalam banyak kasus, kelas akan mendukung beberapa kombinasi tindakan dengan cara yang aman dan lainnya tidak.

Misalnya, banyak koleksi seperti daftar-array dan set hash akan menjamin bahwa jika mereka awalnya diakses secara eksklusif dengan satu utas, dan mereka tidak pernah dimodifikasi setelah referensi menjadi terlihat pada utas lain, mereka dapat dibaca secara sewenang-wenang dengan kombinasi apa pun utas tanpa gangguan.

Lebih menarik, beberapa koleksi hash-set seperti yang non-generik asli di .NET, dapat menawarkan jaminan bahwa selama tidak ada item yang pernah dihapus, dan asalkan hanya satu utas yang pernah menulis kepada mereka, setiap utas yang mencoba untuk membaca koleksi akan berperilaku seolah-olah mengakses koleksi di mana pembaruan mungkin tertunda dan terjadi dalam urutan sewenang-wenang, tetapi yang sebaliknya akan berperilaku normal. Jika utas # 1 menambahkan X dan kemudian Y, dan utas # 2 mencari dan melihat Y dan kemudian X, akan mungkin bagi utas # 2 untuk melihat bahwa Y ada tetapi X tidak; apakah perilaku seperti itu adalah "aman-utas" akan tergantung pada apakah utas # 2 siap untuk menghadapi kemungkinan itu.

Sebagai catatan akhir, beberapa kelas - terutama memblokir perpustakaan komunikasi - mungkin memiliki metode "tutup" atau "Buang" yang aman untuk semua metode lainnya, tetapi tidak ada metode lain yang aman untuk sehubungan dengan satu sama lain. Jika utas melakukan pembacaan permintaan pemblokiran dan pengguna program mengklik "batal", tidak akan ada cara untuk menutup permintaan yang dikeluarkan oleh utas yang mencoba melakukan pembacaan. Permintaan tutup / buang, bagaimanapun, dapat secara tidak sinkron menetapkan bendera yang akan menyebabkan permintaan baca dibatalkan sesegera mungkin. Setelah penutupan dilakukan pada utas apa pun, objek akan menjadi tidak berguna, dan semua upaya tindakan di masa depan akan gagal dengan segera,

supercat
sumber
0

Dengan kata sederhana: P Jika aman untuk mengeksekusi banyak utas pada suatu blok kode maka amankan *

*ketentuan berlaku

Ketentuan disebutkan oleh jawaban lain seperti 1. Hasilnya harus sama jika Anda mengeksekusi satu utas atau beberapa utas di atasnya dll.

lusuh
sumber