Go 的一个 CAS 操作使用场景

``````if len(c) < n {
c <- something // 写入
}``````

``````const (
_CHAN_SIZE  = 10
_GUARD_SIZE = 10
)

var c chan interface{} = make(_CHAN_SIZE + _GUARD_SIZE) // 额外分配了一块保护的空间。

func write(val interface{}) {
if len(c) < _CHAN_SIZE {
c <- val
}
}``````

『弱弱的瞥一眼那个位置(操作)，没人占着咱就占，其他人占着咱也不等，直接走人』

``````// CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value.
func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
...``````

``````func writeMsgWithCASCheck(val interface{}) {
if atomic.CompareAndSwapInt64(&flag, 0, 1) {
if len(c) < _CHAN_SIZE {
c <- val
atomic.StoreInt64(&obj.flag, 0)
return nil
}
atomic.StoreInt64(&obj.flag, 0)
}
}``````

``````func writeMsgWithCASCheck(val interface{}) {
for {
if atomic.CompareAndSwapInt64(&flag, 0, 1) {
if len(c) < _CHAN_SIZE {
...
}
}
}``````

``````\$ go run cas.go
R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(2)+1 R(3)+1 R(1)+1 R(0)+1 R(1)+1 R(2)+1 R(3)+1 Chan overflow, len: 13.
quit.
\$ go run cas.go cas
R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(3)+1 R(1)+1 R(2)+1 R(1)+1 R(0)+1 R(3)+1 R(2)+1 R(1)+1 R(3)+1 R(3)+1 R(3)+1 R(3)+1 R(1)+1 R(2)+1 R(2)+1 R(2)+1 R(3)+1 R(1)+1 R(2)+1 R(3)+1 R(1)+1 R(1)+1 R(2)+1 R(1)+1 R(2)+1 <nil>
quit.``````

``````package main

import (
"errors"
"fmt"
"os"
"sync/atomic"
"time"
)

const (
_CHAN_SIZE  = 10
_GUARD_SIZE = 10

_TEST_CNT = 32
)

type Obj struct {
flag int64
c    chan interface{}
}

func (obj *Obj) readLoop() error {
counter := _TEST_CNT
for {
time.Sleep(5 * time.Millisecond)
if len(obj.c) > _CHAN_SIZE {
return errors.New(fmt.Sprintf("Chan overflow, len: %v.", len(obj.c)))
} else if len(obj.c) > 0 {
<-obj.c
counter--
}
if counter <= 0 {
return nil
}
}
}

func (obj *Obj) writeMsg(idx int, v interface{}) (err error) {
for {
if len(obj.c) < _CHAN_SIZE {
obj.c <- v
fmt.Printf("R(%v)+1 ", idx)
return nil
}
}
}

func (obj *Obj) writeMsgWithCASCheck(idx int, v interface{}) (err error) {
for {
if atomic.CompareAndSwapInt64(&obj.flag, 0, 1) {
if len(obj.c) < _CHAN_SIZE {
obj.c <- v
atomic.StoreInt64(&obj.flag, 0)
fmt.Printf("R(%v)+1 ", idx)
return nil
} else {
atomic.StoreInt64(&obj.flag, 0)
}
}
}

return nil
}

func main() {
useCAS := false
if len(os.Args) > 1 && os.Args[1] == "cas" {
useCAS = true
}
routineCnt := 4
tryCnt := _TEST_CNT / routineCnt
var obj = &Obj{c: make(chan interface{}, _CHAN_SIZE+_GUARD_SIZE)}

for idx := 0; idx < routineCnt; idx++ {
go func(nameIdx int) {
for tryIdx := 0; tryIdx < tryCnt; tryIdx++ {
if useCAS {
obj.writeMsgWithCASCheck(nameIdx, nil)
} else {
obj.writeMsg(nameIdx, nil)
}
}
}(idx)
}

fmt.Println("quit.")
}``````

0 回复

• 请尽量让自己的回复能够对别人有帮助
• 支持 Markdown 格式, **粗体**、~~删除线~~、``单行代码``
• 支持 @ 本站用户；支持表情（输入 : 提示），见 Emoji cheat sheet
• 图片支持拖拽、截图粘贴等方式上传

``````if len(c) < n {
c <- something // 写入
}``````

``````const (
_CHAN_SIZE  = 10
_GUARD_SIZE = 10
)

var c chan interface{} = make(_CHAN_SIZE + _GUARD_SIZE) // 额外分配了一块保护的空间。

func write(val interface{}) {
if len(c) < _CHAN_SIZE {
c <- val
}
}``````

『弱弱的瞥一眼那个位置(操作)，没人占着咱就占，其他人占着咱也不等，直接走人』

``````// CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value.
func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
...``````

``````func writeMsgWithCASCheck(val interface{}) {
if atomic.CompareAndSwapInt64(&flag, 0, 1) {
if len(c) < _CHAN_SIZE {
c <- val
atomic.StoreInt64(&obj.flag, 0)
return nil
}
atomic.StoreInt64(&obj.flag, 0)
}
}``````

``````func writeMsgWithCASCheck(val interface{}) {
for {
if atomic.CompareAndSwapInt64(&flag, 0, 1) {
if len(c) < _CHAN_SIZE {
...
}
}
}``````

``````\$ go run cas.go
R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(2)+1 R(3)+1 R(1)+1 R(0)+1 R(1)+1 R(2)+1 R(3)+1 Chan overflow, len: 13.
quit.
\$ go run cas.go cas
R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(0)+1 R(3)+1 R(1)+1 R(2)+1 R(1)+1 R(0)+1 R(3)+1 R(2)+1 R(1)+1 R(3)+1 R(3)+1 R(3)+1 R(3)+1 R(1)+1 R(2)+1 R(2)+1 R(2)+1 R(3)+1 R(1)+1 R(2)+1 R(3)+1 R(1)+1 R(1)+1 R(2)+1 R(1)+1 R(2)+1 <nil>
quit.``````

``````package main

import (
"errors"
"fmt"
"os"
"sync/atomic"
"time"
)

const (
_CHAN_SIZE  = 10
_GUARD_SIZE = 10

_TEST_CNT = 32
)

type Obj struct {
flag int64
c    chan interface{}
}

func (obj *Obj) readLoop() error {
counter := _TEST_CNT
for {
time.Sleep(5 * time.Millisecond)
if len(obj.c) > _CHAN_SIZE {
return errors.New(fmt.Sprintf("Chan overflow, len: %v.", len(obj.c)))
} else if len(obj.c) > 0 {
<-obj.c
counter--
}
if counter <= 0 {
return nil
}
}
}

func (obj *Obj) writeMsg(idx int, v interface{}) (err error) {
for {
if len(obj.c) < _CHAN_SIZE {
obj.c <- v
fmt.Printf("R(%v)+1 ", idx)
return nil
}
}
}

func (obj *Obj) writeMsgWithCASCheck(idx int, v interface{}) (err error) {
for {
if atomic.CompareAndSwapInt64(&obj.flag, 0, 1) {
if len(obj.c) < _CHAN_SIZE {
obj.c <- v
atomic.StoreInt64(&obj.flag, 0)
fmt.Printf("R(%v)+1 ", idx)
return nil
} else {
atomic.StoreInt64(&obj.flag, 0)
}
}
}

return nil
}

func main() {
useCAS := false
if len(os.Args) > 1 && os.Args[1] == "cas" {
useCAS = true
}
routineCnt := 4
tryCnt := _TEST_CNT / routineCnt
var obj = &Obj{c: make(chan interface{}, _CHAN_SIZE+_GUARD_SIZE)}

for idx := 0; idx < routineCnt; idx++ {
go func(nameIdx int) {
for tryIdx := 0; tryIdx < tryCnt; tryIdx++ {
if useCAS {
obj.writeMsgWithCASCheck(nameIdx, nil)
} else {
obj.writeMsg(nameIdx, nil)
}
}
}(idx)
}