Created
April 16, 2019 15:21
-
-
Save bwangelme/44f0edb469733bf9bac86bbc96faf037 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 ( | |
"fmt" | |
"log" | |
"sync" | |
) | |
const endNum = 30 | |
type FairLock struct { | |
mu *sync.Mutex | |
cond *sync.Cond | |
isHold bool | |
holdCount int | |
} | |
func NewFairLock() sync.Locker { | |
mu := new(sync.Mutex) | |
cond := sync.NewCond(mu) | |
return &FairLock{ | |
holdCount: 0, | |
isHold: false, | |
mu: mu, | |
cond: cond, | |
} | |
} | |
func (fl *FairLock) Lock() { | |
fl.mu.Lock() | |
defer fl.mu.Unlock() | |
if !fl.isHold { | |
fl.holdCount++ | |
fl.isHold = true | |
return | |
} | |
fl.holdCount++ | |
for fl.isHold { | |
fl.cond.Wait() | |
} | |
fl.isHold = true | |
} | |
func (fl *FairLock) Unlock() { | |
fl.mu.Lock() | |
defer fl.mu.Unlock() | |
if !fl.isHold { | |
log.Fatal("unlock of UnLocked mutex") | |
} | |
if fl.holdCount > 1 { | |
fl.cond.Signal() | |
} | |
fl.isHold = false | |
fl.holdCount-- | |
} | |
var ( | |
end = make(chan struct{}) | |
i int | |
) | |
func threadPrint(threadNum int, threadName string, locker sync.Locker) { | |
for i < endNum { | |
locker.Lock() | |
if i >= endNum { | |
locker.Unlock() | |
continue | |
} | |
if i%3 != threadNum { | |
locker.Unlock() | |
continue | |
} | |
fmt.Printf("%d: %s\n", i, threadName) | |
i += 1 | |
locker.Unlock() | |
} | |
end <- struct{}{} | |
} | |
func main() { | |
mu := NewFairLock() | |
names := []string{"A", "B", "C"} | |
for idx, name := range names { | |
go threadPrint(idx, name, mu) | |
} | |
for _ = range names { | |
<-end | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment