Apa itu Iterator fail-safe & fail-fast di Java

101

Ada dua jenis iterator di Java: fail-safe dan fail-fast.

Apa artinya ini, dan apakah perbedaan di antara keduanya?

Prateek
sumber
3
tautan terbaik yang saya temukan javahungry.blogspot.com/2014/04/…
Premraj
2
Perhatikan bahwa spesifikasi Java SE tidak menggunakan istilah "fail-safe" untuk menjelaskan iterator apa pun. Karena itu saya merekomendasikan untuk menghindari istilah ini. Lihat juga stackoverflow.com/a/38341921/1441122
Stuart Marks

Jawaban:

84

Apa perbedaan di antara mereka ...

"Aman dari kegagalan " ( dalam rekayasa ) berarti bahwa sesuatu gagal dengan cara yang tidak menyebabkan kerusakan atau kerusakan minimal. Sebenarnya, tidak ada hal seperti iterator gagal-aman di Java. Jika sebuah iterator gagal (dalam arti normal "gagal"), Anda dapat mengharapkan terjadinya kerusakan.

Saya menduga bahwa yang Anda maksud sebenarnya adalah iterator yang "kurang konsisten". Javadoc mengatakan:

"Sebagian besar implementasi Koleksi serentak (termasuk sebagian besar Antrean) juga berbeda dari konvensi java.util biasa karena Iterator dan Pemisahnya memberikan traversal yang kurang konsisten daripada gagal cepat."

Biasanya, konsistensi yang lemah berarti bahwa jika kumpulan dimodifikasi secara bersamaan dengan iterasi, jaminan dari apa yang dilihat oleh iterasi lebih lemah. (Detailnya akan ditentukan di setiap kelas koleksi bersamaan javadocs.)

"Fail-fast" ( dalam desain sistem ) berarti bahwa kondisi kegagalan diperiksa secara agresif sehingga kondisi kegagalan (jika memungkinkan 1 ) terdeteksi sebelum terlalu banyak kerusakan yang dapat terjadi. Di Java, iterator gagal-cepat gagal dengan menampilkan ConcurrentModificationException.

Alternatif untuk "gagal-cepat" dan "konsisten lemah" adalah semantik di mana iterasi gagal secara tak terduga; misalnya terkadang memberikan jawaban yang salah atau memberikan pengecualian yang tidak terduga. (Ini adalah perilaku beberapa implementasi standar EnumerationAPI di versi awal Java.)

... dan apakah mereka berbeda dari iterator yang kita gunakan untuk koleksi.

Tidak. Ini adalah properti dari iterator yang diimplementasikan oleh tipe Collection standar; yaitu "gagal cepat" atau "konsisten lemah" ... bila digunakan dengan benar sehubungan dengan sinkronisasi dan model memori Java 1 .


Iterator cepat gagal biasanya diimplementasikan menggunakan volatilepenghitung pada objek koleksi.

  • Saat koleksi diperbarui, penghitung bertambah.
  • Ketika sebuah Iteratordibuat, nilai penghitung saat ini tertanam di Iteratorobjek.
  • Saat Iteratoroperasi dilakukan, metode akan membandingkan dua nilai penghitung dan menampilkan CME jika keduanya berbeda.

Sebaliknya, iterator yang kurang konsisten biasanya bersifat ringan dan memanfaatkan properti dari setiap struktur data internal pengumpulan serentak. Tidak ada pola umum. Jika Anda tertarik, baca kode sumber untuk kelas koleksi yang berbeda.


1 - Penunggangnya adalah bahwa perilaku gagal-cepat mengasumsikan bahwa id aplikasi dengan benar sehubungan dengan sinkronisasi dan model memori. Itu berarti bahwa (misalnya) jika Anda mengulang ArrayListtanpa sinkronisasi yang tepat, hasilnya mungkin adalah hasil daftar yang rusak. Mekanisme "kegagalan cepat" mungkin akan mendeteksi modifikasi bersamaan (meskipun itu tidak dijamin), tetapi tidak akan mendeteksi kerusakan yang mendasarinya. Sebagai contoh, javadoc for Vector.iterator()mengatakan ini:

"Perilaku cepat-gagal dari sebuah iterator tidak dapat dijamin karena, secara umum, tidak mungkin untuk membuat jaminan keras apa pun dengan adanya modifikasi serentak yang tidak tersinkronisasi. Iterator cepat-gagal ConcurrentModificationExceptionmelakukan upaya terbaik. Oleh karena itu, itu akan menjadi salah untuk menulis program yang bergantung pada pengecualian ini untuk kebenarannya: perilaku cepat gagal dari iterator harus digunakan hanya untuk mendeteksi bug. "

Stephen C
sumber
Mungkin sedikit tidak relevan tetapi mungkin juga melengkapi pertanyaan ini. Bagaimana dengan gaya snapshot yang digunakan, misalnya Kontrak Karya? Lebih khusus lagi, saya tidak begitu mengerti bagaimana array yang mendasari (atau snapshot) yang diiterasi oleh CoW iterator di atas "tidak pernah" melihat perubahan apa pun yang dibuat oleh thread lain karena kami masih dapat memanggil setArraymodifikasi apa pun.
stdout
Saya memutuskan bahwa berbicara tentang penerapan iterator yang kurang konsisten berada di luar cakupan T&J ini.
Stephen C
42

Mereka adalah tipe yang cepat gagal dan konsisten lemah :

Iterator dari java.utilpelemparan paket ConcurrentModificationExceptionjika koleksi dimodifikasi oleh metode koleksi (tambah / hapus) saat melakukan iterasi

Iterator dari java.util.concurrentpaket biasanya melakukan iterasi melalui snapshot dan memungkinkan modifikasi bersamaan tetapi mungkin tidak mencerminkan pembaruan koleksi setelah iterator dibuat.

Evgeniy Dorofeev
sumber
Iterator adalah contoh gagal-cepat sementara pencacahan aman-gagal
Ajay Sharma
5
@AjaySharma - Salah dalam dua hal. 1) Tidak satu pun Iteratoratau Enumerationtentukan perilaku sebagai gagal-cepat atau gagal-aman. Ini adalah implementasi khusus (yaitu metode collection iterator()/ elements()etc tertentu yang mengembalikan objek-objek ini) yang menentukan perilaku. 2) Implementasi Pencacahan Khas tidak gagal-cepat atau tidak-aman .
Stephen C
22

Satu-satunya perbedaan adalah iterator fail-safe tidak menampilkan Exception apa pun, berbeda dengan Iterator fail-fast.

Jika Collection diubah secara struktural saat satu thread sedang mengulanginya. Ini karena mereka bekerja pada klon Koleksi daripada koleksi asli dan itulah mengapa mereka disebut sebagai iterator gagal-aman.

Iterator dari CopyOnWriteArrayList adalah contoh Iterator yang aman dan juga iterator yang ditulis oleh ConcurrentHashMap keySet juga merupakan iterator yang aman untuk gagal dan tidak pernah memunculkan ConcurrentModificationException di Java.

Juned Ahsan
sumber
Saya tidak melihat iterator ConcurrentHashMap bekerja pada clone () .. :( Beberapa kali itu akan mencerminkan beberapa pembaruan saat iterasi ..
Kanagavelu Sugumar
0

Skenario ini berkaitan dengan "pemrosesan bersamaan", artinya lebih dari satu pengguna mengakses sumber daya yang sama. Dalam situasi seperti itu, salah satu pengguna mencoba mengubah sumber daya yang menyebabkan 'ConcurrentProcessingException' karena dalam kasus tersebut pengguna lain mendapatkan data yang tidak benar. Kedua tipe ini berhubungan dengan situasi seperti ini.

Secara sederhana,

Gagal-Cepat:

  • Iterator segera menampilkan ConcurrentModificationException jika terjadi modifikasi struktural (tambah, perbarui, hapus).
  • Contoh: ArrayList, HashMap, TreeSet

Gagal-Aman:

  • Di sini Iterator tidak mengeluarkan pengecualian apa pun karena mereka beroperasi pada tiruan koleksi, bukan yang asli. Jadi, mereka adalah iterator yang aman dari kegagalan.
  • Contoh: CopyOnWriteArrayList, ConcurrentHashMap
Dhwanil Patel
sumber