Rumah >pembangunan bahagian belakang >Golang >Adakah menggantikan pembolehubah dipetakan dengan benang objek dipetakan baharu selamat?
Editor PHP Apple hadir untuk menjawab soalan biasa: "Adakah ia selamat untuk menggantikan pembolehubah pemetaan dengan objek pemetaan baharu?" Pembolehubah pemetaan ialah struktur data biasa yang digunakan untuk menyimpan pasangan nilai kunci. Dalam persekitaran berbilang benang, keselamatan benang adalah pertimbangan penting. Walaupun menggunakan objek pemetaan baharu boleh mengelakkan masalah akses serentak, sama ada ia selamat untuk benang masih perlu dinilai berdasarkan kes demi kes. Seterusnya, kami akan meneroka isu ini secara mendalam untuk membantu pembaca lebih memahami hubungan antara keselamatan benang dan objek yang dipetakan.
Saya rasa ia tidak selamat untuk benang kerana objek yang dipetakan lebih besar daripada perkataan mesin dan golang tidak menjamin ia selamat untuk benang. Tetapi apabila saya menjalankan kod demo menggunakan go run -race main.go
ia tidak pernah melaporkan ralat. Ini mungkin sebab mengapa threadsanitizer bergantung pada semakan masa jalan dan operasi penugasan untuk mendapati sukar untuk memenuhi keadaan tidak selamat benang.
Berikut ialah kod contoh:
package main import ( "fmt" ) var m = make(map[int]bool) func Read() { for { for k := range m { fmt.Println(k) } } } func Replace() { for { newM := make(map[int]bool, 10) for i := 0; i < 10; i++ { newM[i] = false } m = newM } } func main() { c := make(chan struct{}) go Read() go Replace() <-c }
Jadi bagaimana saya boleh mengubah suai kod untuk mencetuskan ralat konkurensi? Atau mungkin saya salah dan kod itu selamat untuk benang?
Berikut adalah beberapa perkara yang perlu diberi perhatian:
for k := range m {
Ekspresi julat dinilai sekali pada permulaan gelung untuk. Jadi operasi ini akan membaca m
一次(注意,这意味着如果循环中的代码重新分配 m
,则循环将继续迭代原始 m
,但是如果添加新元素或从 m
中删除元素,这些将被检测到循环),循环本身会调用 fmt.println
, yang akan memakan sebahagian besar masa pelaksanaan dalam goroutine ini. Jika anda ingin mengejar permainan, padamkannya.
Kedua, anda sebenarnya tidak perlu memulakan peta kedua.
Apabila anda melakukan ini dan menjalankan pengesan perlumbaan, ia mungkin menangkap perlumbaan data. Setakat yang saya bimbang, ia berlaku.
Pengesan perbalahan akan mengadu tentang perbalahan apabila ia mengesannya. Jadi jika ia melaporkan perlawanan, maka ada perlawanan. Jika tidak dilaporkan, tidak bermakna tiada peraduan.
Pada platform saya, pembolehubah peta itu sendiri sebenarnya sama saiznya dengan perkataan mesin: ia hanyalah penunjuk kepada struktur yang dipetakan. Oleh itu, penulisan kepada pembolehubah dipetakan adalah secara atomik, iaitu anda tidak akan melihat pemetaan yang diperuntukkan sebahagiannya pada platform ini. Walau bagaimanapun, ini tidak menghalang perbalahan kerana tiada jaminan bila goroutine lain akan melihat memori ini ditulis.
Ringkasnya, ia adalah satu pertandingan. Ini bukan kerana saiz pembolehubah peta. Untuk membetulkannya, gunakan mutex.
Atas ialah kandungan terperinci Adakah menggantikan pembolehubah dipetakan dengan benang objek dipetakan baharu selamat?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!