Saya sering menemukan istilah ini digunakan dalam konteks pemrograman bersamaan. Apakah mereka sama atau berbeda?
sumber
Saya sering menemukan istilah ini digunakan dalam konteks pemrograman bersamaan. Apakah mereka sama atau berbeda?
Tidak, mereka bukanlah hal yang sama. Mereka bukan bagian dari satu sama lain. Mereka juga tidak diperlukan, atau kondisi yang cukup untuk satu sama lain.
Definisi balapan data cukup jelas, dan oleh karena itu, penemuannya dapat diotomatiskan. Sebuah ras data terjadi ketika 2 instruksi dari benang yang berbeda mengakses lokasi memori yang sama, setidaknya satu dari akses ini adalah menulis dan tidak ada sinkronisasi yang mewajibkan setiap urutan tertentu antara akses tersebut.
Kondisi balapan adalah kesalahan semantik. Ini adalah kesalahan yang terjadi dalam pengaturan waktu atau urutan kejadian yang mengarah pada perilaku program yang salah. Banyak kondisi balapan dapat disebabkan oleh data race, tetapi ini tidak perlu.
Pertimbangkan contoh sederhana berikut di mana x adalah variabel bersama:
Thread 1 Thread 2
lock(l) lock(l)
x=1 x=2
unlock(l) unlock(l)
Dalam contoh ini, penulisan ke x dari utas 1 dan 2 dilindungi oleh kunci, oleh karena itu penulisan ini selalu terjadi dalam urutan tertentu yang diberlakukan oleh urutan perolehan kunci pada waktu proses. Artinya, tulisan 'atomicity tidak dapat dipatahkan; selalu ada yang terjadi sebelum hubungan antara dua penulisan dalam eksekusi apa pun. Kita tidak bisa tahu tulisan mana yang terjadi sebelum yang lain apriori.
Tidak ada urutan tetap antara penulisan, karena locks tidak dapat menyediakan ini. Jika ketepatan program dikompromikan, katakanlah ketika tulis ke x oleh utas 2 diikuti oleh tulis ke x di utas 1, kita katakan ada kondisi balapan, meskipun secara teknis tidak ada balapan data.
Jauh lebih berguna untuk mendeteksi kondisi balapan daripada data race; namun ini juga sangat sulit untuk dicapai.
Menyusun contoh kebalikannya juga sepele. Posting blog ini juga menjelaskan perbedaannya dengan sangat baik, dengan contoh transaksi bank sederhana.
Menurut Wikipedia, istilah "kondisi balapan" telah digunakan sejak zaman gerbang logika elektronik pertama. Dalam konteks Java, kondisi balapan dapat berkaitan dengan sumber daya apa pun, seperti file, koneksi jaringan, utas dari kumpulan utas, dll.
Istilah "data race" paling baik digunakan untuk arti spesifiknya yang ditentukan oleh JLS .
Kasus yang paling menarik adalah kondisi balapan yang sangat mirip dengan data race, tetapi tetap tidak sama, seperti dalam contoh sederhana ini:
Karena
i
tidak stabil, tidak ada perlombaan data; namun, dari sudut pandang ketepatan program ada kondisi perlombaan karena non-atomicity dari dua operasi: bacai
, tulisi+1
. Beberapa utas dapat menerima nilai yang sama dariuniqueInt
.sumber
data race
sebenarnya berarti di JLS?Tidak, mereka berbeda & tidak satupun dari mereka merupakan bagian dari satu atau sebaliknya.
Diambil dari buku luar biasa - Java Concurrency in Practice oleh Joshua Bloch & Co.
sumber
TL; DR: Perbedaan antara data race dan kondisi ras bergantung pada sifat perumusan masalah, dan di mana harus menggambarkan batas antara perilaku tidak terdefinisi dan perilaku yang terdefinisi dengan baik namun tidak pasti. Perbedaan saat ini bersifat konvensional dan paling mencerminkan antarmuka antara arsitek prosesor dan bahasa pemrograman.
1. Semantik
Perlombaan data secara khusus mengacu pada "akses memori" (atau tindakan, atau operasi) konflik yang tidak disinkronkan ke lokasi memori yang sama. Jika tidak ada konflik dalam akses memori, sementara masih ada perilaku tak tentu yang disebabkan oleh pengurutan operasi, itu adalah kondisi balapan.
Catatan "akses memori" di sini memiliki arti khusus. Mereka mengacu pada tindakan pemuatan atau penyimpanan memori "murni", tanpa semantik tambahan apa pun yang diterapkan. Misalnya, penyimpanan memori dari satu utas tidak (harus) tahu berapa lama data yang akan ditulis ke dalam memori, dan akhirnya menyebar ke utas lain. Untuk contoh lain, penyimpanan memori ke satu lokasi sebelum penyimpanan lain ke lokasi lain dengan utas yang sama tidak (harus) menjamin data pertama yang ditulis dalam memori berada di depan yang kedua. Akibatnya, urutan akses memori murni tersebut tidak (harus) dapat "masuk akal" , dan apa pun bisa terjadi, kecuali ditentukan lain dengan baik.
Ketika "akses memori" didefinisikan dengan baik dalam hal pengurutan melalui sinkronisasi, semantik tambahan dapat memastikan bahwa, bahkan jika waktu akses memori tidak dapat ditentukan, urutannya dapat " dipikirkan " melalui sinkronisasi. Catatan, meskipun urutan antara akses memori dapat dilakukan dengan alasan, mereka belum tentu ditentukan, oleh karena itu kondisi balapannya.
2. Mengapa ada perbedaan?
Namun jika urutannya masih belum tentu dalam kondisi balapan, kenapa repot-repot membedakannya dengan data race? Alasannya lebih praktis daripada teoritis. Itu karena perbedaan memang ada pada antarmuka antara bahasa pemrograman dan arsitektur prosesor.
Instruksi pemuatan / penyimpanan memori dalam arsitektur modern biasanya diimplementasikan sebagai akses memori "murni", karena sifat pipeline yang tidak teratur, spekulasi, cache multi-level, interkoneksi cpu-ram, terutama multi-core, dll. Ada banyak faktor yang menyebabkan waktu dan urutan tidak pasti. Untuk menegakkan pengurutan untuk setiap instruksi memori menimbulkan hukuman yang sangat besar, terutama pada desain prosesor yang mendukung multi-core. Jadi semantik pemesanan dilengkapi dengan instruksi tambahan seperti berbagai penghalang (atau pagar).
Data race adalah situasi eksekusi instruksi prosesor tanpa pagar tambahan untuk membantu menalar urutan akses memori yang bentrok. Hasilnya tidak hanya tidak pasti, tetapi juga mungkin sangat aneh, misalnya, dua penulisan ke lokasi kata yang sama dengan utas yang berbeda dapat menghasilkan setiap tulisan setengah dari kata, atau mungkin hanya beroperasi pada nilai cache lokal mereka. - Ini adalah perilaku yang tidak terdefinisi, dari sudut pandang programmer. Tapi mereka (biasanya) didefinisikan dengan baik dari sudut pandang arsitek prosesor.
Programmer harus memiliki cara untuk alasan eksekusi kode mereka. Data race adalah sesuatu yang tidak masuk akal, oleh karena itu harus selalu dihindari (biasanya). Itulah mengapa spesifikasi bahasa yang levelnya cukup rendah biasanya mendefinisikan data race sebagai perilaku tidak terdefinisi, berbeda dari perilaku memori kondisi ras yang terdefinisi dengan baik.
3. Model memori bahasa
Prosesor yang berbeda mungkin memiliki perilaku akses memori yang berbeda, yaitu model memori prosesor. Sangat canggung bagi programmer untuk mempelajari model memori dari setiap prosesor modern dan kemudian mengembangkan program yang dapat memanfaatkannya. Diinginkan jika bahasa dapat menentukan model memori sehingga program dari bahasa tersebut selalu berperilaku seperti yang diharapkan seperti yang ditentukan oleh model memori. Itulah mengapa Java dan C ++ memiliki model memorinya yang ditentukan. Ini adalah beban pengembang kompilator / waktu proses untuk memastikan model memori bahasa diterapkan di seluruh arsitektur prosesor yang berbeda.
Artinya, jika suatu bahasa tidak ingin mengekspos perilaku prosesor tingkat rendah (dan bersedia mengorbankan keunggulan kinerja tertentu dari arsitektur modern), mereka dapat memilih untuk menentukan model memori yang sepenuhnya menyembunyikan detail "murni" memori mengakses, tetapi menerapkan semantik pengurutan untuk semua operasi memorinya. Kemudian pengembang compiler / runtime dapat memilih untuk memperlakukan setiap variabel memori sebagai volatile di semua arsitektur prosesor. Untuk bahasa ini (yang mendukung memori bersama di seluruh utas), tidak ada balapan data, tetapi mungkin masih berupa kondisi balapan, bahkan dengan bahasa dengan konsistensi urutan lengkap.
Di sisi lain, model memori prosesor bisa lebih ketat (atau kurang santai, atau pada level yang lebih tinggi), misalnya, menerapkan konsistensi sekuensial seperti yang dilakukan prosesor awal. Kemudian semua operasi memori diurutkan, dan tidak ada balapan data untuk bahasa apa pun yang berjalan di prosesor.
4. Kesimpulan
Kembali ke pertanyaan awal, IMHO boleh saja mendefinisikan data race sebagai kasus khusus dari kondisi balapan, dan kondisi balapan di satu level dapat menjadi data race di level yang lebih tinggi. Itu tergantung pada sifat perumusan masalah, dan di mana harus menarik batas antara perilaku tidak terdefinisi dan perilaku yang terdefinisi dengan baik tetapi tidak pasti. Hanya konvensi saat ini yang mendefinisikan batasan pada antarmuka pemroses bahasa, tidak selalu berarti selalu dan harus demikian; tetapi konvensi saat ini mungkin paling mencerminkan antarmuka canggih (dan kebijaksanaan) antara arsitek prosesor dan bahasa pemrograman.
sumber