Created
September 5, 2012 12:48
-
-
Save royguo/3636063 to your computer and use it in GitHub Desktop.
Lock Free Queue Problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"sync/atomic" | |
"unsafe" | |
"sync" | |
"fmt" | |
"time" | |
) | |
const ( | |
MAX_DATA_SIZE = 100 | |
) | |
// lock free queue | |
type Queue struct { | |
head unsafe.Pointer | |
tail unsafe.Pointer | |
} | |
// one node in queue | |
type Node struct { | |
val interface{} | |
next unsafe.Pointer | |
} | |
// queue functions | |
func (self *Queue) enQueue(val interface{}) { | |
newValue := unsafe.Pointer(&Node{val: val, next: nil}) | |
var tail,next unsafe.Pointer | |
for { | |
tail = self.tail | |
next = ((*Node)(tail)).next | |
if next != nil { | |
atomic.CompareAndSwapPointer(&(self.tail), tail, next) | |
}else if atomic.CompareAndSwapPointer(&((*Node)(tail).next), nil, newValue){ | |
break | |
} | |
} | |
} | |
func (self *Queue) deQueue() (val interface{}, success bool){ | |
var head,tail,next unsafe.Pointer | |
for { | |
head = self.head | |
tail = self.tail | |
next = ((*Node)(head)).next | |
if head == tail { | |
if next == nil { | |
return nil, false | |
}else { | |
atomic.CompareAndSwapPointer(&(self.tail), tail, next) | |
} | |
}else { | |
val = ((*Node)(next)).val | |
if atomic.CompareAndSwapPointer(&(self.head), head, next) { | |
return val, true | |
} | |
} | |
} | |
return | |
} | |
func main() { | |
var wg sync.WaitGroup | |
wg.Add(20) | |
queue := new(Queue) | |
queue.head = unsafe.Pointer(new(Node)) | |
queue.tail = queue.head | |
for i := 0; i < 10; i++ { | |
go func() { | |
defer wg.Done() | |
for j := 0; j < MAX_DATA_SIZE; j++ { | |
t := time.Now() | |
queue.enQueue(t) | |
fmt.Println("enq = ", t) | |
} | |
}() | |
} | |
for i := 0; i < 10; i++ { | |
go func() { | |
ok := false | |
var val interface{} | |
defer wg.Done() | |
for j := 0; j < MAX_DATA_SIZE; j++ { | |
val,ok = queue.deQueue() | |
for !ok { | |
val,ok = queue.deQueue() | |
} | |
fmt.Println("deq = ",val) | |
} | |
}() | |
} | |
wg.Wait() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment