分享
  1. 首页
  2. 文章

golang使用sync保证container/list链表线程安全

rfyiamcool · · 3690 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一边python,一边golang ! 时常因为工作切换语言造成了短路。container/list是golang语言内置的链表库。 对比其他语言的list,container/list该有的功能都有,就缺一个popLeft popRight方法。如果要实现pop方法需要去除value := list.Back() , 然后list.Remove(value) 。但这样不能保持操作的原子性。 解决的方法是用全局的互斥锁。

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。

http://xiaorui.cc/?p=2923


下面是 container/list 包的基本用法.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#xiaorui.cc
func(e*Element)Next()*Element//返回该元素的下一个元素,如果没有下一个元素则返回nil
func(e*Element)Prev()*Element//返回该元素的前一个元素,如果没有前一个元素则返回nil
func New()*List//返回一个初始化的list
func(l*List)Back()*Element//获取listl的最后一个元素
func(l*List)Front()*Element//获取listl的第一个元素
func(l*List)Init()*List//listl初始化或者清除listl
func(l*List)InsertAfter(vinterface{},mark*Element)*Element//listl中元素mark之后插入一个值为v的元素,并返回该元素,如果mark不是list中元素,则list不改变。
func(l*List)InsertBefore(vinterface{},mark*Element)*Element//listl中元素mark之前插入一个值为v的元素,并返回该元素,如果mark不是list中元素,则list不改变。
func(l*List)Len()int//获取listl的长度
func(l*List)MoveAfter(e,mark*Element)//将元素e移动到元素mark之后,如果元素e或者mark不属于listl,或者e==mark,则listl不改变。
func(l*List)MoveBefore(e,mark*Element)//将元素e移动到元素mark之前,如果元素e或者mark不属于listl,或者e==mark,则listl不改变。
func(l*List)MoveToBack(e*Element)//将元素e移动到listl的末尾,如果e不属于listl,则list不改变。
func(l*List)MoveToFront(e*Element)//将元素e移动到listl的首部,如果e不属于listl,则list不改变。
func(l*List)PushBack(vinterface{})*Element//listl的末尾插入值为v的元素,并返回该元素。
func(l*List)PushBackList(other*List)//listl的尾部插入另外一个list,其中lother可以相等。
func(l*List)PushFront(vinterface{})*Element//listl的首部插入值为v的元素,并返回该元素。
func(l*List)PushFrontList(other*List)//listl的首部插入另外一个list,其中lother可以相等。
func(l*List)Remove(e*Element)interface{}//如果元素e属于listl,将其从list中删除,并返回元素e的值。

需要说明的是,container/list默认不是线程安全的,应该说大多数语言自带的list都不能确保数据安全。 如果你想保证数据安全,那么可以使用Lock锁解决。

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#xiaorui.cc
package main
import(
"container/list"
"fmt"
)
func main(){
//生成队列
l:=list.New()
//入队,压栈
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.PushBack(4)
//出队
v1:=l.Front()
l.Remove(v1)
fmt.Printf("%d\n",v1.Value)
//出栈
a1:=l.Back()
l.Remove(a1)
fmt.Printf("%d\n",a1.Value)
}


如果你是在goroutine协程环境下使用container/list链表,那么一定要记得加锁。 代码如下:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#xiaorui.cc
#xiaorui.cc
package main
import(
"fmt"
"sync"
)
func main(){
varl*sync.Mutex
l=new(sync.Mutex)
l.Lock()
deferl.Unlock()
fmt.Println("1")
}


使用container/list包结合sync的mutex互斥锁造了一个支持线程安全的链表。

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package main
import(
"container/list"
"fmt"
"sync"
"time"
)
typeQueuestruct{
data*list.List
}
func NewQueue()*Queue{
q:=new(Queue)
q.data=list.New()
returnq
}
func(q*Queue)push(vinterface{}){
defer lock.Unlock()
lock.Lock()
q.data.PushFront(v)
}
func(q*Queue)pop()interface{}{
defer lock.Unlock()
lock.Lock()
iter:=q.data.Back()
v:=iter.Value
q.data.Remove(iter)
returnv
}
func(q*Queue)dump(){
foriter:=q.data.Back();iter!=nil;iter=iter.Prev(){
fmt.Println("item:",iter.Value)
}
}
var lock sync.Mutex
func main(){
q:=NewQueue()
go func(){
q.push("one")
}()
go func(){
q.push("four")
}()
q.push("two")
q.push("three")
v:=q.pop()
fmt.Println("pop v:",v)
fmt.Println("......")
time.Sleep(1*time.Second)
q.dump()
}

上面那段go代码运行后的结果:

Python
1
2
3
4
5
6
popv:two
......
item:three
item:one
item:four

有疑问加站长微信联系(非本文作者)

本文来自:峰云就她了

感谢作者:rfyiamcool

查看原文:golang使用sync保证container/list链表线程安全

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3690 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏