Seri Konkurensi Swift 05|Perbedaan antara Aktor dan metode penulisan thread-safe tradisional
Aktor bukanlah "Swift lock". Apa yang sebenarnya mereka ubah adalah bagaimana negara bersama diorganisir.
Saat Anda pertama kali mendengar Actor, secara tidak sadar Anda akan memahaminya sebagai “alat keamanan thread yang disediakan oleh Swift”.
Pemahaman ini tidak sepenuhnya salah, namun jika berhenti sampai disini saja maka akan mudah untuk menulis kode yang “menggunakan aktor, namun strukturnya masih berantakan”.
Karena hal terpenting tentang Actor adalah mengubah ide default:
Keadaan bersama yang bisa berubah tidak boleh diekspos ke semua orang terlebih dahulu dan kemudian mencari cara untuk melindunginya; pendekatan yang lebih masuk akal adalah dengan mengisolasinya terlebih dahulu dan kemudian memutuskan bagaimana mengaksesnya dari luar.
Ini mungkin terdengar seperti perbedaan dalam kata-katanya, tetapi sebenarnya ini merupakan titik balik dalam kebiasaan desain konkurensi.
1. Hal paling berbahaya dalam konkurensi sering kali adalah keadaan bersama yang bisa berubah
Kebanyakan bug konkurensi dimulai dari:
- Dua tugas membaca dan menulis cache yang sama secara bersamaan
- Satu tugas belum ditulis, dan tugas lainnya sudah dibuat penilaian berdasarkan nilai lama.
- Beberapa halaman mengubah status global secara bersamaan
- Layanan tertentu bertanggung jawab untuk menyegarkan token, menggunakan token, dan menyiarkan hasilnya.
Masalah-masalah ini mungkin muncul dalam berbagai bentuk, namun akar penyebabnya seringkali sama: **Keadaan bersama yang bisa berubah tidak memiliki batasan yang jelas. **
Jika batasan negara bagian tidak jelas, perubahan apa pun dalam urutan penjadwalan tugas dapat memperbesar bug.
2. Masalah dengan solusi keamanan benang tradisional adalah solusi tersebut tidak cukup terpusat.
Solusi yang biasa kami gunakan di masa lalu meliputi:
NSLock- antrian serial
- kunci baca-tulis
- Kesepakatan tim bahwa “objek ini hanya dapat diakses pada antrian tertentu”
Tidak satu pun dari solusi ini yang salah, dan banyak sistem yang matang masih digunakan secara stabil hingga saat ini. Masalah sebenarnya mereka adalah:
**Aturan akses mudah tersebar. **
Pada awalnya Anda mungkin masih ingat:
- Cache ini harus diakses dengan kunci
- Kamus itu hanya dapat diubah dalam antrian serial
- Status tertentu hanya dapat dibaca dan ditulis di thread utama
Namun seiring bertambahnya jumlah titik panggilan, aturan-aturan ini perlahan-lahan akan terdistorsi. Hal yang paling menjengkelkan tentang bug konkurensi adalah seringkali tidak mungkin lagi memastikan bahwa seluruh tim secara ketat mematuhi aturan-aturan yang tersebar tersebut.
3. Ide inti Aktor adalah “kurangi berbagi terlebih dahulu”
Ini adalah poin terpenting yang perlu diulangi.
Ide tradisionalnya lebih seperti:
- Pertama mempunyai status bersama
- Kemudian pikirkan cara untuk melindunginya melalui kuncian, antrian, dan konvensi
Ide aktor lebih dekat:
- Negara ini tidak boleh diakses secara sembarangan.
- Saya masukkan ke dalam batas isolasi terlebih dahulu
- Dunia luar hanya dapat berinteraksi dengannya melalui antarmuka yang terkontrol
Perubahan terbesar yang ditimbulkannya adalah kita terpaksa memikirkan tentang kepemilikan status, alih-alih menyetujui bahwa setiap orang dapat menyentuhnya secara langsung.
Misalnya, jika koordinator penyegaran token hanyalah objek global dengan sekumpulan kunci, mentalitas defaultnya adalah “Semua orang menggunakan status ini, dan saya harus melindunginya.”
Jika Actor, mentalitas defaultnya akan menjadi “Keadaan ini dikelola olehnya, dan orang lain hanya dapat menanyakan hasil atau mengirim perintah.”
Beginilah perubahan desain.
4. Pendekatan isolasi ini lebih cocok untuk proyek yang kompleks
Karena yang paling ditakuti oleh proyek-proyek kompleks adalah proliferasi peraturan.
Setelah akses negara diblokir oleh Aktor, banyak masalah yang akan terungkap sebelumnya:
-Siapa yang mengontrol data ini?
- Apakah persyaratan eksternal merupakan gambaran singkat, nilai turunan, atau operasi imperatif?
- Operasi mana yang harus memiliki semantik serial dan mana yang hanya berupa kueri baca-saja
Masalah-masalah ini sering kali muncul kembali di model lama, karena setiap orang secara default “berbagi terlebih dahulu, lalu mengunci jika ada masalah”. Sebaliknya, para aktor memaksakan desain batas lebih awal.
Oleh karena itu, saya lebih suka menganggap Aktor sebagai alat desain konkurensi daripada sekadar alat keamanan thread.
5. Di mana tempat terbaik untuk menempatkan Aktor?
Tidak semua objek layak dijadikan Aktor. Ini lebih cocok untuk peran yang sekaligus memenuhi karakteristik berikut:
- Telah berbagi keadaan yang bisa berubah
- Akan diakses secara bersamaan dengan banyak tugas
- Konsistensi itu penting
- Metode akses perlu dikoordinasikan secara terpusat
Contoh umumnya meliputi:
- Koordinator cache gambar
- Koordinator penyegaran token
- Unduh pusat pendaftaran tugas
- Semacam pengakses sumber daya global
- Pusat pesan yang memerlukan konsumsi acara secara serial
Kesamaan dari objek-objek ini adalah bahwa mereka merupakan pusat negara yang berbagi tugas dan rentan terhadap masalah konkurensi.
Jika ini hanya layanan fungsi murni, atau objek status yang hanya digunakan sebentar di dalam satu halaman, Aktor mungkin tidak diperlukan.
6. Apa perbedaan mendasar antara Aktor dan “Tambahkan kunci ke seluruh kelas”?
Di permukaan, mereka semua dapat melakukan “banyak tugas tanpa mengubah status”. Namun pengalaman tekniknya sangat bervariasi.
Saat mengunci seluruh kelas, pertanyaan umum adalah:
- Penelepon masih bisa mendapatkan banyak detail internal
- Perincian kunci dapat dengan mudah lepas kendali
- Beberapa metode memanggil sumber daya sinkronisasi lainnya, membentuk sarang yang kompleks.
- Anggota tim masih dapat mengabaikan aturan dan langsung mengakses status yang tidak boleh mereka akses
Aktor, setidaknya pada tingkat semantik, dengan jelas mengungkapkan:
- Status ini tidak dibagikan secara bebas
- Akses lintas-isolasi harus secara eksplisit melewati batas asinkron
- Mengakses keadaan ini sendiri merupakan perilaku yang dibatasi
Dengan kata lain, Aktor tidak hanya “membantu menambah perlindungan”, tetapi juga membuat metode akses yang tidak aman menjadi lebih sulit untuk ditulis dengan santai.
7. Aktor tidak dapat menyelesaikan apa pun
Hal ini harus diperjelas. Saat pertama kali mempelajari konten ini, Anda akan memiliki ilusi bahwa keamanan thread akan diserahkan pada masa depan.
Faktanya, Aktor hanya memecahkan satu jenis masalah: mengisolasi keadaan bersama.
Itu tidak menyelesaikan:
- Apakah rangkaian bisnis itu masuk akal?
- Haruskah tugas lama dilanjutkan setelah meninggalkan halaman?
- Apakah hasilnya telah kedaluwarsa
- Apakah batas negara salah?
Misalnya, jika cache hasil pencarian dibuat menjadi aktor, namun halaman masih mengizinkan permintaan lama untuk menimpa hasil kata kunci baru, maka bug akan tetap ada. Karena masalahnya di sini adalah “validitas hasil” tidak dimodelkan sejak awal.
Jadi Aktor memang penting, tapi mereka bukanlah obat mujarab untuk konkurensi.
8. Dua arahan Aktor yang paling mudah disalahgunakan
1. Cobalah untuk memasukkan semuanya ke dalam Aktor
Begitu aktor dianggap sebagai label “lebih aman selama mereka digunakan”, mereka akan mulai mengemas secara berlebihan:
- Status yang jelas-jelas hanya digunakan dalam konteks single-thread juga dikemas sebagai Aktor
- Logika yang jelas lebih cocok untuk pemrosesan fungsi murni juga dipaksakan ke dalam Aktor
- Pada akhirnya, seluruh sistem penuh dengan batas akses asinkron, dan struktur menjadi lebih berat.
Lebih banyak Aktor tidak selalu lebih baik. Kuncinya adalah menempatkan mereka di tempat yang benar-benar dibutuhkan untuk mengisolasi diri.
2. Perlakukan Aktor sebagai “bukti keamanan”
Setelah aktor ditambahkan ke beberapa kode, tim akan berasumsi bahwa potongan kode tersebut “aman untuk thread”. Namun banyak bug berasal dari:
- Desain siklus hidup yang salah
- Aliran keadaan salah
- Hubungan tugas yang salah
Aktor dapat menjamin “Jangan main-main dengan konkurensi dan sentuh keadaan internal saya”, tetapi tidak dapat menjamin “proses bisnis sudah benar”.
9. Pertanyaan penilaian yang lebih praktis
Jika Anda ragu apakah suatu objek harus dirancang sebagai Aktor, saya sarankan Anda tidak bertanya “Apakah itu tidak aman untuk thread” terlebih dahulu, tetapi tanyakan terlebih dahulu:
- Apakah ada status bersama yang bisa berubah di dalamnya?
- Apakah status ini dapat diakses oleh banyak tugas secara bersamaan?
- Apakah saya ingin dunia luar berinteraksi dengannya hanya melalui antarmuka yang terkontrol?
- Jika batas isolasi tidak ditambah, apakah kedepannya akan mudah disalahgunakan oleh tim?
Jika jawaban atas sebagian besar pertanyaan di atas adalah “ya”, maka kemungkinan besar jawaban tersebut cocok untuk Aktor tersebut.
10. Kesimpulan: Nilai sebenarnya dari Aktor adalah mengubah status bersama yang dapat diubah dari paparan default ke isolasi default.
Singkatnya, saya akan mengatakan:
ActorYang benar-benar berubah adalah “keadaan bersama yang dapat diubah akhirnya tidak lagi diekspos ke semua orang secara default.”
Pemikiran tradisionalnya lebih seperti: berbagi dulu, baru lindungi. Ide dari Aktor adalah: isolasi dulu, lalu putuskan cara mengaksesnya.
Dalam sistem konkuren yang kompleks, perubahan pemikiran ini seringkali lebih penting daripada “satu lagi alat keamanan thread”.
What to read next
Want more posts about Swift Concurrency?
Posts in the same category are usually the best next step for reading more on this topic.
View same categoryWant to keep following #Swift Concurrency?
Tags are useful for related tools, specific problems, and similar troubleshooting notes.
View same tagWant to explore another direction?
If you are not sure what to read next, return to the homepage and start from categories, topics, or latest updates.
Back home