2010-10-17 51 views
9

Các kênh kết hợp giao tiếp — trao đổi giá trị — với đồng bộ hóa — đảm bảo rằng hai phép tính (goroutines) đang ở trạng thái đã biết.Làm thế nào chúng ta có thể sử dụng các kênh trong Go thay cho mutex?

Làm cách nào để sử dụng các kênh trong Google Go để thực hiện chức năng của mutex?

package main 

import "sync" 

var global int = 0 
var m sync.Mutex 

func thread1(){ 
    m.Lock() 
    global = 1 
    m.Unlock() 
} 

func thread2(){ 
    m.Lock() 
    global = 2 
    m.Unlock() 
} 

func main(){ 
    go thread1() 
    go thread2() 
} 
+3

Câu hỏi này loại bỏ lỡ điểm. Bạn nên tự hỏi mình "tại sao tôi muốn một mutex, và làm thế nào tôi có thể sử dụng các kênh thay thế?" –

Trả lời

17

Một ví dụ của việc sử dụng một kênh như một Mutex:

package main 

var global int = 0 
var c = make(chan int, 1) 

func thread1(){ 
    <-c // Grab the ticket 
    global = 1 
    c <- 1 // Give it back 
} 

func thread2(){ 
    <-c 
    global = 2 
    c <- 1 
} 

func main() { 
    c <- 1 // Put the initial value into the channel 
    go thread1() 
    go thread2() 
} 
+0

Cảm ơn câu trả lời MizardX. – Kevin

+0

Giải pháp tuyệt vời !! – HaltingState

+2

Trong khi các kênh cung cấp một giải pháp tốt đẹp cho dữ liệu được bảo vệ, nó là một giải pháp ít hiệu quả hơn trong trường hợp của một nhà văn và nhiều độc giả. –

4

Nếu bạn có một kênh c mà bạn khởi tạo với 1 mục trong nó, sau đó bạn có thể "kiểm tra" the "mutex" bằng cách loại bỏ các giá trị từ các kênh (<-c). Bạn có thể "giải phóng" bằng cách thêm giá trị trở lại (c <- 1).

Vì toán tử trích xuất từ ​​kênh a) là nguyên tử, và b) khối cho đến khi có thứ gì đó để trích xuất, nó hoạt động như một mutex, vì nếu một luồng thực hiện đã kiểm tra, sẽ không có gì trong kênh, và do đó nó sẽ chặn cho đến khi luồng mà nó đã kiểm tra trả về một giá trị cho kênh cho một luồng khác để trích xuất.

+0

Cảm ơn Amber. Chúng ta có thể có ví dụ được hiển thị ở trên được triển khai bằng cách sử dụng kênh thay vì mutex không? – Kevin

Các vấn đề liên quan