# 1. 如何使用Channel模拟锁

> 此开源图书由[ithaiq](https://github.com/ithaiq)原创，创作不易转载请注明出处

1. 我们封装一个struct操作mutex锁

```go
type Test struct {
	count int
	g sync.Mutex
}

func (t *Test) add() {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.count++
}
func (t *Test) reduce() {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.count--
}
```

2\. 愉快的执行main函数测试

```go
func main() {
	var t = &Test{}
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 0; i < 100000; i++ {
			t.add()
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < 100000; i++ {
			t.reduce()
		}
	}()
	wg.Wait()
	fmt.Println(t.count)
}
```

3\. 重头戏使用channel模拟锁

```go
type Lock struct {
	ch chan struct{}
}

func (l *Lock) Lock() {
	l.ch <- struct{}{}
}
func (l *Lock) Unlock() {
	select {
	case <-l.ch:
	default:
		panic("不可重复解锁")
	}
}
```

4\. 最后我们把Test结构体里面的mutex字段类型换成\*Lock，完美perfect
