Entonces ayer, según informó hoy principalmente concurrente de seguridad, bloqueo y dos ejemplo simple de la tela
1. Seguridad concurrente y bloqueo
Dado que se trata de seguridad, no sería seguro para hablar de por qué. Ayer dijo concurrencia goroutine, por lo que si el acceso goroutine múltiple cuando no hay sincronización entre sí a la vez un recurso y realiza operaciones I / O, y que esta vez les llamamos a un estado competitivo, se conoce como una carrera. Echemos un vistazo en el ejemplo de una raza
package main
import (
"fmt"
"runtime"
"sync"
)
var (
count int //定义一个全局变量,之后会对它进行操作
wg1 sync.WaitGroup
)
func incCounter(id int) {
defer wg1.Done()
for i := 0; i < 2; i++ {
value := count
runtime.Gosched()
value++
count = value
}
}
func main() {
wg1.Add(2)
go incCounter(1)
go incCounter(2)
wg1.Wait()
fmt.Println("最后的count值为:", count)
}
Analizar, obviamente, con los dos goroutine, y cada goroutine se realizará dos veces, los resultados no deben ser de 4 ¿verdad? ¿Por qué es 2. En esta ocasión se trata de la raza, es decir, cada goroutine cubrirá el funcionamiento de otros goroutine, por lo que ha habido errores. Esta vez la importancia de la cerradura se manifiesta, por supuesto, también podemos utilizar la función atómica para eliminar la influencia de la raza, pero sólo es compatible con algunos tipos integrados de datos primitivos, por lo que el bloqueo es la más crítica. El más utilizado es el mutex (exclusión mutua), se puede garantizar al mismo tiempo sólo una goroutine puede acceder al recurso, y luego mutex para modificar el código anterior para ver el efecto.
package main
import (
"fmt"
"runtime"
"sync"
)
var (
count int //定义一个全局变量,之后会对它进行操作
wg1 sync.WaitGroup
mutex sync.Mutex
)
func incCounter(id int) {
defer wg1.Done()
for i := 0; i < 2; i++ {
mutex.Lock()
value := count
runtime.Gosched()
value++
count = value
mutex.Unlock()
}
}
func main() {
wg1.Add(2)
go incCounter(1)
go incCounter(2)
wg1.Wait()
fmt.Println("最后的count值为:", count)
}
Además, el resultado de un mutex
de manera normal, por lo mutex puede ser una buena carrera para evitar el problema.
Cuando una operación de lectura es mucho mayor que la operación de escritura, con un simple exclusión mutua no es un gran desperdicio, esta vez no es un mutex de lectura-escritura
package main
import (
"fmt"
"sync"
"time"
)
//读写互斥锁:读的次数远远大于写的次数
var (
x1 int64
wg1 sync.WaitGroup
lock1 sync.Mutex //互斥锁
rwlock sync.RWMutex //读写互斥锁
)
func read() {
//lock1.Lock()
rwlock.RLock()
time.Sleep(time.Millisecond)
//lock1.Unlock()
rwlock.RUnlock()
wg1.Done()
}
func write() {
//lock1.Lock()
rwlock.Lock()
x1 += 1
time.Sleep(time.Millisecond * 10)
//lock1.Unlock()
rwlock.Unlock()
wg1.Done()
}
func main() {
start := time.Now()
for i := 0; i < 1000; i++ {
wg1.Add(1)
go read()
}
for i := 0; i < 10; i++ {
wg1.Add(1)
go write()
}
wg1.Wait()
fmt.Println(time.Now().Sub(start))
}
//sync.Once 只运行一次
//sync.Map 并发安全的map并且是空接口类型,Store、Load、LoadorStore、Delete、Range
Con este ejemplo se encuentra el número en el caso de la lectura es mucho mayor que el número de escritura y de lectura y escritura de velocidad mutex será mucho más rápido que utilizar un mutex.
Ejemplos de 2.web
El 1.Web "Hola mundo"
package main
import (
"fmt"
"net/http"
)
func handle(write http.ResponseWriter, request *http.Request) {
fmt.Fprintf(write, "hello world,%s!", request.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handle)
http.ListenAndServe(":8081", nil)
El código es muy simple, es para configurar el puerto para iniciar su servicio web, a continuación, imprimir hola mundo y la información URL de puerto
2. Un simple servidor y las comunicaciones del cliente
del servidor
package main
import (
"bufio"
"fmt"
"net"
)
//tcp server demo
func process(conn net.Conn) {
defer conn.Close()
for {
reader := bufio.NewReader(conn)
var buf [128]byte
n, err := reader.Read(buf[:])
if err != nil {
fmt.Printf("read from conn failed,err:%v\n", err)
break
}
recv := string(buf[:n])
fmt.Println("接收到的数据为:", recv)
conn.Write([]byte("ok"))
}
}
func main() {
listen, err := net.Listen("tcp", "127.0.0.1:20000")
if err != nil {
fmt.Printf("listen failed,err:%v\n", err)
return
}
for {
conn, err := listen.Accept()
if err != nil {
fmt.Printf("accept failed,err:%v\n", err)
continue
}
go process(conn)
}
}
cliente
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
//1.与服务端建立连接
conn, err := net.Dial("tcp", "127.0.0.1:20000")
if err != nil {
fmt.Printf("dial failed,err:%v\n", err)
return
}
//2.利用连接发送接收数据
input := bufio.NewReader(os.Stdin)
for {
s, _ := input.ReadString('\n')
s = strings.TrimSpace(s)
if strings.ToUpper(s) == "Q" {
return
}
//给服务端发消息
_, err := conn.Write([]byte(s))
if err != nil {
fmt.Printf("senf failed,err:%v\n", err)
return
}
//从服务器接受回复的消息
var buf [1024]byte
n, err := conn.Read(buf[:])
if err != nil {
fmt.Printf("read failed,err:%v\n", err)
return
}
fmt.Println("收到服务端回复:", string(buf[:n]))
}
}
El resultado:
de hecho utilizan, sobre todo marco de desarrollo web, al igual que el frasco de Python, Django ...... java de SSM, ssh ...... así que salga lenguaje web, entonces también utilizar el marco, por lo que recientemente se destinará a aprender el conocimiento de ginebra .