В чем разница между конкурентностью и параллелизмом в Go

Ответ

Конкурентность (Concurrency) — это способность программы декомпозировать задачи на независимые части и выполнять их в произвольном порядке (например, с помощью горутин и каналов в Go). Это о структурировании программы для обработки нескольких вещей одновременно.

Параллелизм (Parallelism) — это одновременное выполнение этих задач на нескольких ядрах CPU или процессорах. Это о фактическом выполнении нескольких вещей в один и тот же момент времени.

Ключевое отличие:

  • Конкурентностьлогическая модель. Программа может быть конкурентной, но выполняться на одном ядре CPU через быстрое переключение контекста (мультиплексирование).
  • Параллелизмфизическое выполнение. Требует наличия нескольких ядер CPU или процессоров для одновременного выполнения задач.

Пример:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func task(name string) {
    for i := 0; i < 3; i++ {
        fmt.Printf("Task %s: %dn", name, i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    // Конкурентность: запуск двух горутин.
    // Они могут выполняться на одном ядре (чередуясь) или на разных (параллельно),
    // в зависимости от планировщика Go и доступных ресурсов.
    go task("A")
    go task("B")

    // Параллелизм: Go-рантайм по умолчанию использует GOMAXPROCS,
    // равный количеству логических ядер CPU. Если доступно более одного ядра,
    // горутины могут выполняться параллельно.
    // Можно явно установить GOMAXPROCS, чтобы ограничить или увеличить количество ядер.
    // Например, для принудительного использования 2 ядер:
    // runtime.GOMAXPROCS(2)

    fmt.Printf("Number of logical CPUs: %dn", runtime.NumCPU())
    fmt.Printf("GOMAXPROCS: %dn", runtime.GOMAXPROCS(0)) // GOMAXPROCS(0) возвращает текущее значение

    // Даем время горутинам завершиться
    time.Sleep(1 * time.Second)
    fmt.Println("Main finished")
}

Go делает конкурентность простой и естественной благодаря горутинам и каналам, а параллелизм становится возможным, когда есть доступные аппаратные ресурсы и GOMAXPROCS позволяет их использовать.

Ответ 18+ 🔞

Давай разберём эту тему, а то народ путает, как последние идиоты, блядь. Конкурентность и параллелизм — это не одно и то же, ёпта! Это как сравнивать хуй с пальцем — вроде похоже, а нахуя-то разное.

Конкурентность (Concurrency) — это когда твоя программа умеет распиливать задачи на куски и жонглировать ими, как цирковой урод. Выполнять их можно в любом порядке, главное — создать видимость, что всё идёт одновременно. В Go это горутины с каналами, которые тебе мозги выносят, если не понять, как они работают. Это про структуру, про то, как ты код организовал, чтобы он мог казаться многозадачным.

Параллелизм (Parallelism) — а вот это уже физика, блядь! Это когда твои распиленные задачи реально, в один момент времени выполняются на нескольких ядрах процессора. Не "кажется", а вот прямо прямо сейчас на ядре №1 и ядре №2. Это про железо, про то, сколько у тебя этих ядер в компе.

Разница, которая бьёт по мозгам:

  • Конкурентность — это логическая хуйня. Ты можешь написать конкурентную программу, а она будет бегать на одном ядре, просто переключаясь между задачами быстрее, чем ты успеешь сказать "ёбаный насос".
  • Параллелизм — это физическая пизда. Нужны реальные несколько ядер, иначе нихуя не будет одновременности.

Пример, чтобы окончательно вьебать в голову:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func task(name string) {
    for i := 0; i < 3; i++ {
        fmt.Printf("Task %s: %dn", name, i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    // Конкурентность: запускаем две горутины. Они могут бегать на одном ядре, по очереди.
    go task("A")
    go task("B")

    // Параллелизм: Go по умолчанию использует все ядра.
    // Если ядер больше одного — горутины могут разбежаться по ним и работать параллельно.
    // Можно, конечно, и ограничить, если ты любитель страданий.
    // runtime.GOMAXPROCS(1) // Вот так загонишь всё на одно ядро, и будет конкурентность без параллелизма, ебать.

    fmt.Printf("Логических ядер CPU: %dn", runtime.NumCPU())
    fmt.Printf("GOMAXPROCS (сколько ядер использует Go): %dn", runtime.GOMAXPROCS(0))

    time.Sleep(1 * time.Second)
    fmt.Println("Main закончил, все свободны.")
}

Короче, Go тебе даёт конкурентность на блюдечке с горутинами, а параллелизм — это уже как повезёт с железом и настройками. Главное — не путай, а то получишь код, который выглядит как многопоточный, а работает как хуй сгоревший.