myStack
890 subscribers
761 photos
15 videos
27 files
310 links
Меня зовут Ростислав и я разработчик.

Это мой личный блог.

Я пишу на Go, читаю книги про технологии и пишу об этих и других вещах сюда.


Книги:
https://bit.ly/rostislav-books

Личка:
https://t.me/Rostislaved

Сайт:
Rostislav.me
Download Telegram
Data race (или просто гонка)

Представим, что есть некий код, который запускает 2 параллельных потока, внутри каждого в цикле, например 1 млн раз, происходит одна операция:
а = а + 1
где а - одна и та же переменная (например глобальная).

Ожидаемый результат - a == 2 млн
Фактический результат - a < 2 млн. Точное значение всегда разное.

Так происходит потому что a = a + 1 для процессора на самом деле является не одной операцией, а тремя:
1. Взять из оперативки значение в переменной а и поместить ее в регистр процессора
2. Прибавить к этому значению 1 (результат суммирования лежит в регистре)
3. Сохранить результат из регистра в оперативную память

И при параллельной работе с этой переменной порядок этих операцией не гарантируется. То есть нет гарантии в каком порядке потоки ОС будут выполнять эти операции. Отсюда и возникает состояние гонки.

Пример.
Допустим есть 2 потока ОС. Работу начинает первый. a = 0
1 поток. Выполнил 1. (в регистре: 0, в оперативке а=0)
1 поток. Выполнил 2. (в регистре: 1, в оперативке а=0)
Переключение контекста (начал работу второй поток)
2 поток. Выполнил 1. (в регистре: 0, в оперативке а=0)
2 поток. Выполнил 2. (в регистре: 1, в оперативке а=0)
2 поток. Выполнил 3. (в регистре: 1, в оперативке а=1)
Переключение контекста (начал работу первый поток)
1 поток. Выполнил 3 (в регистре: 1, в оперативке а=1)

Таким образом, после того, как 2 потока сделали a = a + 1 в переменной лежит не 2, а 1.

Чтобы избежать состояния гонки надо запретить двум потокам одновременный доступ к общему участку памяти (Участок кода, где это происходит называется критическая секция).

Сделать это можно с помощью мьтекса (лок): до операции над критической секцией делаем Lock(), после операции над критической секцией делаем Unlock().

Суть этого в том, что пока один поток "держит" лок, то другой поток при попытке сделать Lock() блокируется и ждет, пока другой поток не сделает Unlock(). В результате этого все 3 операции для инкремента переменной всегда происходят атомарно и проблемы возникнуть не может.

Пример кода:
https://go.dev/play/p/BGzDCig5dGQ

package main

import (
"fmt"
"sync"
)

var a = 0

func main() {
var wg sync.WaitGroup

wg.Add(1)
go increment(&wg)

wg.Add(1)
go increment(&wg)

wg.Wait()
fmt.Println(a)
}

func increment(wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; i < 1e6; i++ {
a = a + 1
}
}
👍2🔥1
У DeliveryClub есть крутая Pro подписка, которая делает доставку бесплатной во многих местах.

Стоит 100р в месяц (первый вообще 1р). С учетом того, что сама доставка без подписки 129р за 1 раз, то это очень выгодно.
1
btw если вас напрягает дублирование в чате и в канале, из одного из них или из двух можно ливнуть :)
Вк - мастер аналитики.
2й скрин - эта Елизавета
3й скрин - я
🔥3
Подход европейских и рускоговорящих рекрутеров.

(полезной инфы на втором скрине больше)

PS: европейские, пощадите..
🔥1
Хочу быть бэтманом, чтобы у меня был двроецкий.
Узнал, что в Go оказывается есть возможность создавать плагины. То есть файлы с расширением .so подгружаемые в рантайме.

Правда нужно, чтобы версия файла и основной программы совпадала.

Также, как более гибкий аналог есть реализация от HashiCorp, но тут эти плагины - отдельные процессы, а общение через rpc.
Заметочка.
В гексогональной архитектуре, которая по-другому называется порты и адаптеры:
порты - интерфейсы
адаптеры - реализации этих интерфейсов
Посоветуйте рестораны\кафешки в Москве, где заказывали еду и понравилось?

У меня в списке:
Авлабар - грузинская. Беру люля и фри, иногда хинкали
Маки Маки - роллы. Нравится сет один.
Ями Ями - пицца. Нравится пицца с уткой и горгонзолой, да и в целом ок пиццы тут.
Sky фо, и\или Bo - фо бо.
Чосон - рамен куриный.
The gold standard allowed for unprecedented global capital accumulation and trade by uniting the majority of the planet’s economy on one sound market-based choice of money. Its tragic flaw, however, was that by centralizing the gold in the vaults of banks, and later central banks, it made it possible for banks and governments to increase the supply of money beyond the quantity of gold they held, devaluing the money and transferring part of its value from the money’s legitimate holders to the governments and banks.
Фанаты вайлдберриса, как вы что-то в нем ищите? Я не понимаю...
Сижу играюсь с Go.

Да он быстрый и все такое, но все равно удивляюсь.

Написал программу, которая просто поднимает http-сервер и имеет 1 эндпоинт, внутри которого ничего не происходит.

И запустил горутину, которая каждые 100 мс пишет в stdout текущее число горутин.

И запустил нагрузочное тестирование этого одного бедного эндпоинта через утилиту ab. Один млн запросов в 1000 потоков.

И вот на скрине собственно количество горутин в моментах. Много. И это каждые 100 мс.
💩1