mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
improve gmutex
This commit is contained in:
@ -39,9 +39,8 @@ func New() *Mutex {
|
||||
// Lock blocks until the lock is available.
|
||||
func (m *Mutex) Lock() {
|
||||
for {
|
||||
// If there're no readers pending and writing lock currently,
|
||||
// then do the writing lock checks.
|
||||
if m.reader.Val() == 0 && m.state.Cas(0, -1) {
|
||||
// If there're no writing lock currently, then do the writing lock checks.
|
||||
if m.state.Cas(0, -1) {
|
||||
return
|
||||
}
|
||||
m.writer.Add(1)
|
||||
@ -55,13 +54,11 @@ func (m *Mutex) Lock() {
|
||||
func (m *Mutex) Unlock() {
|
||||
if m.state.Cas(-1, 0) {
|
||||
// Writing lock unlocks, then first check the blocked readers.
|
||||
if n := m.reader.Val(); n > 0 {
|
||||
// If there're readers blocked, unlock them with preemption.
|
||||
for ; n > 0; n-- {
|
||||
m.reading <- struct{}{}
|
||||
}
|
||||
return
|
||||
// If there're readers blocked, unlock them with preemption.
|
||||
for n := m.reader.Val(); n > 0; n-- {
|
||||
m.reading <- struct{}{}
|
||||
}
|
||||
// Then it also gives the pending writers one chance.
|
||||
if m.writer.Val() > 0 {
|
||||
m.writing <- struct{}{}
|
||||
}
|
||||
@ -72,7 +69,7 @@ func (m *Mutex) Unlock() {
|
||||
// It returns true if success, or if there's a write/reading lock on the mutex,
|
||||
// it returns false.
|
||||
func (m *Mutex) TryLock() bool {
|
||||
if m.reader.Val() == 0 && m.state.Cas(0, -1) {
|
||||
if m.state.Cas(0, -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -84,9 +81,8 @@ func (m *Mutex) TryLock() bool {
|
||||
func (m *Mutex) RLock() {
|
||||
var n int32
|
||||
for {
|
||||
// If there're no writing lock and pending writers currently,
|
||||
// then do the reading lock checks.
|
||||
if n = m.state.Val(); n >= 0 && m.writer.Val() == 0 {
|
||||
// If there're no writing lock currently, then do the reading lock checks.
|
||||
if n = m.state.Val(); n >= 0 {
|
||||
if m.state.Cas(n, n+1) {
|
||||
return
|
||||
} else {
|
||||
@ -94,6 +90,7 @@ func (m *Mutex) RLock() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Or else pending the reader.
|
||||
m.reader.Add(1)
|
||||
<-m.reading
|
||||
@ -116,7 +113,7 @@ func (m *Mutex) RUnlock() {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Reading lock unlocks, then first check the blocked writers.
|
||||
// Reading lock unlocks, then check the blocked writers.
|
||||
if n == 1 && m.writer.Val() > 0 {
|
||||
// No readers blocked, then the writers can take place.
|
||||
m.writing <- struct{}{}
|
||||
@ -128,7 +125,7 @@ func (m *Mutex) RUnlock() {
|
||||
func (m *Mutex) TryRLock() bool {
|
||||
var n int32
|
||||
for {
|
||||
if n = m.state.Val(); n >= 0 && m.writer.Val() == 0 {
|
||||
if n = m.state.Val(); n >= 0 {
|
||||
if m.state.Cas(n, n+1) {
|
||||
return true
|
||||
} else {
|
||||
|
||||
@ -49,7 +49,9 @@ func Benchmark_GMutex_LockUnlock(b *testing.B) {
|
||||
|
||||
func Benchmark_GMutex_TryLock(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
gmu.TryLock()
|
||||
if gmu.TryLock() {
|
||||
defer gmu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,11 +8,11 @@ import (
|
||||
)
|
||||
|
||||
func Error1() error {
|
||||
return errors.New("test")
|
||||
return errors.New("test1")
|
||||
}
|
||||
|
||||
func Error2() error {
|
||||
return gerror.New("test")
|
||||
return gerror.New("test2")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
@ -8,11 +8,11 @@ import (
|
||||
)
|
||||
|
||||
func Error1() error {
|
||||
return errors.New("test")
|
||||
return errors.New("test1")
|
||||
}
|
||||
|
||||
func Error2() error {
|
||||
return gerror.New("test")
|
||||
return gerror.New("test2")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
23
geg/errors/gerror/gerror4.go
Normal file
23
geg/errors/gerror/gerror4.go
Normal file
@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/g/errors/gerror"
|
||||
)
|
||||
|
||||
func OpenFile() error {
|
||||
return gerror.New("permission denied")
|
||||
}
|
||||
|
||||
func OpenConfig() error {
|
||||
return gerror.Wrap(OpenFile(), "configuration file opening failed")
|
||||
}
|
||||
|
||||
func ReadConfig() error {
|
||||
return gerror.Wrap(OpenConfig(), "reading configuration failed")
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(gerror.Cause(ReadConfig()))
|
||||
}
|
||||
22
geg/errors/gerror/gerror5.go
Normal file
22
geg/errors/gerror/gerror5.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
|
||||
"github.com/gogf/gf/g/errors/gerror"
|
||||
)
|
||||
|
||||
func Error1() error {
|
||||
return errors.New("test1")
|
||||
}
|
||||
|
||||
func Error2() error {
|
||||
return gerror.New("test2")
|
||||
}
|
||||
|
||||
func main() {
|
||||
glog.Println(Error1())
|
||||
glog.Println(Error2())
|
||||
}
|
||||
29
geg/os/gmutex/gmutex_basic.go
Normal file
29
geg/os/gmutex/gmutex_basic.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/os/gmutex"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mu := gmutex.New()
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(n int) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
glog.Println("Lock:", n)
|
||||
time.Sleep(time.Second)
|
||||
}(i)
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(n int) {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
glog.Println("RLock:", n)
|
||||
time.Sleep(time.Second)
|
||||
}(i)
|
||||
}
|
||||
time.Sleep(11 * time.Second)
|
||||
}
|
||||
22
geg/os/gmutex/gmutex_func.go
Normal file
22
geg/os/gmutex/gmutex_func.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
|
||||
"github.com/gogf/gf/g/os/gmutex"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mu := gmutex.New()
|
||||
go mu.LockFunc(func() {
|
||||
glog.Println("lock func1")
|
||||
time.Sleep(1 * time.Second)
|
||||
})
|
||||
time.Sleep(time.Millisecond)
|
||||
go mu.LockFunc(func() {
|
||||
glog.Println("lock func2")
|
||||
})
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
Reference in New Issue
Block a user