Penguncian sumber daya dengan async/menunggu

Saya memiliki aplikasi di mana saya memiliki sumber daya bersama (sistem Gerak) yang dapat diakses oleh banyak klien. Saya memiliki Operasi individual yang memerlukan akses ke sistem selama perpindahan dan yang harus memunculkan pengecualian 'Sibuk' jika operasi yang bertentangan diminta pada saat yang sama. Saya juga memiliki Sequencer yang perlu memperoleh akses eksklusif ke sistem Gerak untuk melaksanakan beberapa Operasi, diselingi dengan tindakan lain; selama keseluruhan urutan, tidak ada klien lain yang dapat menjalankan Operasi.

Saya secara tradisional melakukan pendekatan ini menggunakan afinitas Thread, sehingga Thread dapat meminta akses eksklusif dan menjalankan panggilan pemblokiran yang sesuai dengan operasi. Meskipun Thread memiliki akses, tidak ada Thread lain yang dapat menggunakan sumber daya tersebut. Masalah yang saya alami sekarang adalah saya telah beralih ke implementasi sistem saya menggunakan pola async/menunggu, untuk memungkinkan implementasi sequencer yang lebih bersih. Masalahnya adalah sekarang sequencer saya tidak selalu berjalan di thread yang sama; thread aktif dapat berubah selama panggilan balik, sehingga tidak lagi mudah untuk menentukan apakah saya berada dalam konteks yang valid untuk terus menjalankan operasi. Satu hal yang perlu diperhatikan adalah bahwa beberapa Operasi itu sendiri terdiri dari menunggu, yang berarti urutan dan Operasi individual dapat menjangkau beberapa thread.

Pertanyaan saya: apakah ada yang tahu pola yang baik untuk menangani perolehan akses eksklusif dengan adanya peralihan thread karena async/menunggu?

Sebagai referensi, beberapa hal yang saya pertimbangkan:

  1. Saya dapat membuat SynchronizationContext khusus yang mengatur semua panggilan sequencer selama durasi urutan kembali ke satu Thread. Keuntungannya adalah memungkinkan saya menggunakan kembali kode manajemen akses afinitas thread yang ada. Kelemahannya adalah hal ini memerlukan dedikasi sebuah Thread setiap kali saya melakukan Urutan atau Operasi (karena Operasi juga dapat menjangkau beberapa thread.)

  2. Buat token akses yang dapat diperoleh untuk diteruskan ke metode Operasi untuk membuktikan bahwa Anda telah memperoleh akses. Ini memiliki kelemahan yaitu membengkaknya metode dengan parameter token.

  3. Gunakan pendekatan token akses dari (2), tetapi buat implementasi antarmuka duplikat untuk antarmuka Operasi sehingga pembungkus dapat dibuat instance-nya dengan token yang 'dipanggang'. Ini menciptakan beberapa kode lem jelek, tetapi membersihkan kode sequencer sehingga tidak perlu lagi meneruskan token ke setiap metode.


person Dan Bryant    schedule 02.10.2012    source sumber


Jawaban (2)


Pertanyaan saya: apakah ada yang tahu pola yang baik untuk menangani perolehan akses eksklusif dengan adanya peralihan thread karena async/menunggu?

Ya, Anda dapat menggunakan AsyncLock, yaitu juga tersedia sebagai bagian dari pustaka AsyncEx saya. Jika Anda ingin memiliki jenis operasi "TryLock", Anda mungkin harus membuat primitif Anda sendiri.

Anda kehilangan sebagian kemampuan untuk melakukan pemeriksaan keamanan: tidak ada cara untuk memeriksa apakah thread yang sedang dijalankan memiliki AsyncLock tertentu.

Opsi lainnya termasuk ConcurrentExclusiveSchedulerPair (yang saya blogkan tentang di sini) atau Aliran Data TPL.

person Stephen Cleary    schedule 02.10.2012
comment
Saya akan menandai ini sebagai jawaban untuk bacaan bermanfaat. Saya akhirnya membuat proxy untuk antarmuka yang menyertakan pemeriksaan akses. Saya kemudian dapat membagikan proxy 'akses eksklusif' khusus sekali pakai yang mencegah contoh proxy lain menggunakan sistem saat sistem masih hidup. - person Dan Bryant; 06.10.2012

Ada SemaphoreSlim.WaitAsync yang sangat cocok di sini. (Saya menemukannya di pertanyaan serupa).

person bohdan_trotsenko    schedule 16.11.2015