Adakah Golang concurrency tidak selamat?

PHPz
Lepaskan: 2023-03-30 09:17:17
asal
877 orang telah melayarinya

Golang, sebagai bahasa pengaturcaraan yang agak muda, telah menarik lebih banyak perhatian dan kasih sayang dengan perkembangan pesatnya sejak beberapa tahun kebelakangan ini. Mekanisme konkurensi terbina dalam Golang menjadikannya disukai oleh ramai pembangun, tetapi penggunaan mekanisme konkurensi akan menyebabkan beberapa bahaya tersembunyi, terutamanya apabila konkurensi tidak selamat, ia mungkin menyebabkan beberapa masalah dalam program. Artikel ini akan meneroka sebab dan penyelesaian untuk konkurensi yang tidak selamat di Golang.

1. Sebab mengapa concurrency tidak selamat

1 Keadaan perlumbaan

Syarat perlumbaan merujuk kepada apabila berbilang rangkaian mengakses sumber yang dikongsi, disebabkan oleh operasi yang berbeza, hasil Kekacauan berlaku, keadaan yang dipanggil keadaan perlumbaan. Di Golang, keadaan perlumbaan lebih jelas disebabkan oleh pelaksanaan coroutine yang tidak segerak.

2. Pertandingan data

Persaingan data bermakna berbilang coroutine mengakses kawasan memori yang sama pada masa yang sama, dan sekurang-kurangnya satu coroutine sedang menjalankan operasi tulis. Disebabkan oleh mekanisme konkurensi Golang, coroutine yang berbeza mempunyai masa pelaksanaan yang berbeza, jadi berbilang coroutine boleh mengubah suai kawasan memori yang sama pada masa yang sama.

3. Deadlock

Deadlock merujuk kepada situasi di mana dua atau lebih coroutine sedang menunggu antara satu sama lain untuk melepaskan sumber dan tidak dapat meneruskan pelaksanaan. Keadaan ini mungkin berlaku apabila menggunakan kunci Jika kunci digunakan secara tidak betul, jalan buntu akan berlaku.

2. Contoh konkurensi tidak selamat di Golang

Berikut ialah contoh mudah untuk menjelaskan masalah konkurensi tidak selamat di Golang:

package main 
import (
   "fmt"
   "sync"
)
var num = 0 
func add(wg *sync.WaitGroup) {
   num++ 
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg)
   }
   wg.Wait()
   fmt.Println("num=", num)
}
Salin selepas log masuk

Dalam contoh ini, kami Nombor pembolehubah global ditakrifkan dan coroutine digunakan untuk memanggil kaedah tambah untuk menambah nombor 1000 kali. Disebabkan oleh pelaksanaan tak segerak bagi coroutine, susunan pelaksanaan program ini tidak pasti. Jika kod ini menjalankan berbilang coroutine pada masa yang sama, persaingan data akan berlaku dan hasil num mungkin bukan 1000 yang kami jangkakan.

3. Bagaimana untuk mengelakkan konkurensi yang tidak selamat di Golang

1 Gunakan kunci

Kunci adalah salah satu kaedah yang biasa digunakan untuk menyelesaikan masalah konkurensi yang tidak selamat kunci Pelaksanaan, seperti sync.Mutex, sync.RWMutex, dsb. Penggunaan kunci boleh memastikan bahawa hanya satu coroutine boleh mengakses sumber tertentu pada masa yang sama, dengan itu mengelakkan berlakunya persaingan data.

Ubah suai contoh di atas dan gunakan penyegerakan.Mutex untuk mengelakkan perlumbaan data:

package main 
import (
   "fmt"
   "sync"
)
var num = 0 
func add(wg *sync.WaitGroup, lock *sync.Mutex) {
   lock.Lock() 
   num++ 
   lock.Unlock()
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   var lock sync.Mutex 
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg, &lock)
   }
   wg.Wait()
   fmt.Println("num=", num)
}
Salin selepas log masuk

Dalam contoh ini, kami menggunakan penyegerakan.Mutex untuk memastikan pengubahsuaian kepada num adalah atom . Ini mengelakkan berlakunya perlumbaan data.

2. Gunakan operasi atom

Golang menyediakan satu siri operasi atom untuk memastikan bahawa operasi sumber tertentu adalah atom. Gunakan operasi atom untuk mengelakkan keadaan perlumbaan, seperti AddInt32, AddInt64, SwapInt32, SwapInt64, dsb. dalam pakej penyegerakan/atomik.

Ubah suai contoh di atas dan gunakan operasi atom untuk mengelakkan perlumbaan data:

package main 
import (
   "fmt"
   "sync/atomic"
   "sync"
)
var num int32 
func add(wg *sync.WaitGroup) {
   atomic.AddInt32(&num,1) 
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg)
   }
   wg.Wait()
   fmt.Println("num=", num)
}
Salin selepas log masuk

Dalam contoh ini, kami menggunakan fungsi AddInt32 dalam pakej penyegerakan/atomik untuk memastikan pengubahsuaian kepada nombor adalah Atom, mengelakkan keadaan perlumbaan.

3. Gunakan saluran

Saluran ialah mekanisme penyegerakan yang sangat biasa digunakan dalam pengaturcaraan serentak Golang boleh memastikan bahawa komunikasi antara coroutine disegerakkan, dengan itu mengelakkan keadaan perlumbaan dan isu Pertandingan data.

Ubah suai contoh di atas untuk menggunakan saluran bagi mengelakkan perlumbaan data:

package main 
import (
   "fmt"
   "sync"
)
func add(wg *sync.WaitGroup, ch chan int) {
   ch <- 1 
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   ch := make(chan int, 1000)
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg, ch)
   }
   wg.Wait()
   close(ch)
   num := 0 
   for n := range ch {
      num += n
   }
   fmt.Println("num=", num)
}
Salin selepas log masuk

Dalam contoh ini, kami menggunakan saluran untuk memastikan pengubahsuaian kepada num disegerakkan, sekali gus mengelakkan penampilan perlumbaan data .

4. Ringkasan

Mekanisme konkurensi Golang adalah salah satu ciri yang sangat menarik, tetapi penggunaan mekanisme konkurensi juga membawa isu keselamatan tertentu. Artikel ini membincangkan sebab dan penyelesaian bagi keadaan Golang yang tidak selamat, dan menyediakan penyelesaian terutamanya dari aspek mengelakkan persaingan data, keadaan perlumbaan dan kebuntuan secara serentak. Dalam proses pengaturcaraan sebenar, kita boleh memilih mekanisme yang sesuai mengikut keperluan khusus untuk memastikan kualiti dan keselamatan program.

Atas ialah kandungan terperinci Adakah Golang concurrency tidak selamat?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan