Pertanyaan Threading dan iterasi melalui perubahan koleksi


Di C # (aplikasi konsol) Saya ingin menyimpan koleksi objek. Semua objek memiliki tipe yang sama. Saya ingin mengulang melalui koleksi yang memanggil metode pada setiap objek. Dan kemudian ulangi prosesnya terus menerus. Namun selama iterasi objek dapat ditambahkan atau dihapus dari daftar. (Benda-benda itu sendiri tidak akan dihancurkan .. hanya dihapus dari daftar). Tidak yakin apa yang akan terjadi dengan loop foreach .. atau metode serupa lainnya. Ini harus dilakukan 1000 kali sebelumnya .. bisakah Anda merekomendasikan pendekatan yang solid?


4
2018-06-10 05:30


asal


Jawaban:


Ada juga pendekatan berbasis salinan. Algoritma ini seperti itu:

  1. ambil kunci pada koleksi bersama
  2. salin semua item dari koleksi bersama ke beberapa koleksi lokal
  3. lepaskan kunci pada koleksi bersama
  4. Iterasi item di koleksi lokal

Keuntungan dari pendekatan ini adalah Anda mengambil kunci pada koleksi bersama untuk jangka waktu kecil (dengan asumsi bahwa koleksi bersama relatif kecil).

Jika metode yang ingin Anda gunakan pada setiap item koleksi membutuhkan waktu yang cukup lama untuk menyelesaikan atau dapat memblokir, maka pendekatan iterasi di bawah kunci bersama dapat menyebabkan pemblokiran untaian lain yang ingin menambah / menghapus item dari koleksi bersama

Namun, jika metode yang ingin Anda gunakan pada setiap objek relatif cepat, maka pengulangan berdasarkan kunci bersama dapat lebih disukai.


1
2018-06-11 15:50



Ini adalah kasus klasik sinkronisasi dalam multithreading.

Hanya pendekatan yang solid dan pendekatan yang lebih baik adalah sinkronisasi antara pengulangan dan penambahan / penghapusan item dari daftar.

Berarti Anda harus mengizinkan penambahan / penghapusan hanya di akhir akhir dan mulai dari loop iterasi!

sesuatu seperti ini:-

    ENTER SYNC_BLOCK
      WAIT FOR SYNC_BLOCK to be available

      LOOP for items/ call method on them.

     LEAVE SYNC_BLOCK


     ENTER SYNC_BLOCK
      WAIT FOR SYNC_BLOCK to be available

     Add/Delete items

 LEAVE SYNC_BLOCK

0
2018-06-10 05:40



Apa yang terlintas dalam pikiran ketika saya membaca contoh ini adalah bahwa Anda bisa menggunakan C5  TreeSet/TreeBag. Itu memang mengharuskan ada cara untuk memesan barang Anda, tetapi keuntungan dari Tree koleksi adalah bahwa mereka menawarkan Snapshot metode (anggota dari C5.IPersistentSorted) yang memungkinkan Anda untuk membuat foto-foto ringan dari keadaan koleksi tanpa perlu membuat duplikat lengkap.

misalnya.:

using(var copy = mySet.Snapshot()) {
  foreach(var item in copy) {
    item.DoSomething();
  }
}

C5 juga menawarkan cara sederhana untuk "berlaku untuk semua" dan kompatibel dengan .NET 2.0:

using(var copy = mySet.Snapshot()) {
  copy.Apply(i => i.DoSomething());
}

Penting untuk dicatat bahwa snapshot harus dibuang atau Anda akan dikenakan penalti kinerja kecil pada modifikasi berikutnya ke koleksi dasar.

Contoh ini dari sangat teliti Buku C5.


0
2017-08-27 14:52