1. 程式人生 > >Go語言實現執行緒安全訪問佇列

Go語言實現執行緒安全訪問佇列

這個例子用Go語言的包"container/list"實現一個執行緒安全訪問的佇列。其中不少細節耐人尋味,做出它則是花費了不少精力,找不到樣例啊!

Go語言的許多優點自不必說,然而從C/C++程式角度看,語言的語法也好,程式的實現方式也好,看起來總有點怪怪的感覺。

在這個程式的基礎上,是很容易實現一個執行緒安全訪問的堆疊的。

Go語言程式:

// structlist project main.go
package main

import (
	"container/list"
	"fmt"
	"sync"
)

const N int = 10

type QueueNode struct {
	figure  int
	digits1 [N]int
	digits2 [N]int
	sflag   bool

	data *list.List
}

var lock sync.Mutex

func newQueue() *QueueNode {
	q := new(QueueNode)
	q.data = list.New()
	return q
}

func (q *QueueNode) push(v interface{}) {
	defer lock.Unlock()
	lock.Lock()
	q.data.PushFront(v)
}

func (q *QueueNode) dump() {
	for iter := q.data.Back(); iter != nil; iter = iter.Prev() {
		fmt.Println("item:", iter.Value)
	}
}

func (q *QueueNode) pop() interface{} {
	defer lock.Unlock()
	lock.Lock()
	iter := q.data.Back()
	v := iter.Value
	q.data.Remove(iter)
	return v
}

func main() {
	var n QueueNode

	n.figure = 1
	n.digits1[0] = 1
	n.digits2[0] = 1
	n.sflag = true

	n2 := n
	n2.digits1[n2.figure] = 2
	n2.digits2[n2.figure] = 2
	n2.figure++
	n2.sflag = false

	n3 := n2
	n3.digits1[n2.figure] = 3
	n3.digits2[n2.figure] = 4
	n3.figure++

	q := newQueue()
	q.push(n)
	q.push(n2)
	q.push(n3)

	q.dump()

	fmt.Printf("\nlen=%d\n\n", q.data.Len())

	for q.data.Len() > 0 {
		x := q.pop().(QueueNode)
		output_node(&x)
	}

}

func output_node(n *QueueNode) {
	fmt.Printf("Figure =%d\n", n.figure)

	fmt.Printf("Array1: ")
	for i := n.figure - 1; i >= 0; i-- {
		fmt.Printf("%d ", n.digits1[i])
	}
	fmt.Println("")

	fmt.Printf("Array2: ")
	for i := n.figure - 1; i >= 0; i-- {
		fmt.Printf("%d ", n.digits2[i])
	}
	fmt.Println("")

	if n.sflag {
		fmt.Printf("SFlag=true\n")
	} else {
		fmt.Printf("SFlag=false\n")
	}

	fmt.Println("")
}


程式執行結果:

item: {1 [1 0 0 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0 0 0] true <nil>}
item: {2 [1 2 0 0 0 0 0 0 0 0] [1 2 0 0 0 0 0 0 0 0] false <nil>}
item: {3 [1 2 3 0 0 0 0 0 0 0] [1 2 4 0 0 0 0 0 0 0] false <nil>}

len=3

Figure =1
Array1: 1 
Array2: 1 
SFlag=true

Figure =2
Array1: 2 1 
Array2: 2 1 
SFlag=false

Figure =3
Array1: 3 2 1 
Array2: 4 2 1 
SFlag=false


程式說明:

1.介面型別轉結構型別,花費了好多時間,其做法堪稱一絕,見79行。

2.全域性變數lock是佇列訪問鎖。

3.佇列使用來資源鎖,設計成執行緒安全訪問的。

4.程式中並沒有使用goroutine,如果需要可以使用類似這樣的程式碼"go func() { q.push(n) }()"