Resumir algunos de los conocimientos más importantes del punto de idioma ir (2)

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)
}

Aquí Insertar imagen Descripción
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
Aquí Insertar imagen Descripción
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
Aquí Insertar imagen Descripción
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:
Aquí Insertar imagen Descripción
Aquí Insertar imagen Descripción
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 .

Publicado 85 artículos originales · ganado elogios 55 · Vistas a 20000 +

Supongo que te gusta

Origin blog.csdn.net/shelgi/article/details/103929345
Recomendado
Clasificación