• 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("
    len=%d
    
    ", 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.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
    ")
    	} else {
    		fmt.Printf("SFlag=false
    ")
    	}
    
    	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) }()"

  • 相关阅读:
    .NET Task揭秘(一)
    .net线程池内幕
    Branch 向量化
    让你的gdb print 更可读
    获取web项目的绝对路径的方法总结
    Android事件监听(一)——简介篇
    Android事件监听(二)——点击鼠标事件
    jsp运行环境的安装和配置
    log4j中的DailyRollingFileAppender日志输出器工作原理
    开发环境搭建
  • 原文地址:https://www.cnblogs.com/tigerisland/p/7563544.html
Copyright © 2020-2023  润新知