← Назад к вопросам

Что такое многопоточность (multithreading)?

2.3 Middle🔥 221 комментариев
#Конкурентность и горутины

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое многопоточность (Multithreading)?

Многопоточность — это модель выполнения программы, позволяющая использовать несколько потоков выполнения (threads) внутри одного процесса. Поток представляет собой последовательность инструкций, которые могут выполняться независимо или параллельно с другими потоками того же процесса. Все потоки процесса совместно используют его ресурсы: память (heap), открытые файлы, сетевые соединения, но имеют собственные стеки вызовов и регистры.

Ключевые преимущества многопоточности

  • Улучшенная производительность и использование ресурсов: Позволяет эффективно использовать многопроцессорные/многопоточные системы (CPU с несколькими ядрами), распределяя задачи между ядрами. Это особенно важно для операций, связанных с ожиданием (I/O, сетевые запросы), где один поток может блокироваться, а другие продолжать работу.
  • Отделение логики для повышения читаемости: Разделение разных аспектов программы на потоки (например, GUI, вычисления, сетевые операции) делает код более структурированным.
  • Экономия ресурсов системы: Потоки легче процессов — создание и переключение между потоками требует меньше ресурсов ОС, поскольку они находятся внутри одного процесса.

Многопоточность в языке Go

В Go многопоточность реализована через модель легковесных потоков — goroutines (горутин), которые не являются потоками ОС в традиционном смысле. Они управляются планировщиком Go, который распределяет их по небольшому количеству реальных потоков ОС (M:N scheduling). Это позволяет создавать тысячи и миллионы горутин с минимальными затратами памяти (начальный размер стека ~2KB).

package main

import (
	"fmt"
	"time"
)

func main() {
    // Запуск горутины - просто добавьте ключевое слово `go`
    go printNumbers()

    // Главный поток продолжает выполнение
    fmt.Println("Main thread continues...")
    time.Sleep(1 * time.Second) // Ждем завершения горутины (на практике используют sync.WaitGroup или каналы)
}

func printNumbers() {
    for i := 1; i <= 5; i++ {
        fmt.Printf("Goroutine: %d\n", i)
        time.Sleep(100 * time.Millisecond)
    }
}

Основные проблемы и механизмы синхронизации в многопоточности

При совместном использовании памяти несколькими потоками возникают классические проблемы:

  1. Race conditions (состояния гонки): Неопределённый результат из-за неконтролируемого порядка доступа к данным.
  2. Deadlocks (взаимные блокировки): Потоки бесконечно ждут друг друга из-за захваченных ресурсов.

Go предоставляет несколько инструментов для безопасной многопоточности, делая коммуникацию через общую память (shared memory) нежелательной и предпочитая коммуникацию через каналы (channels):

// Использование канала для синхронизации и передачи данных
package main

import "fmt"

func worker(id int, jobs <-chan int, results chan<- int) {
    for job := range jobs {
        results <- job * 2 // Отправляем результат
    }
}

func main() {
    jobs := make(chan int, 5)
    results := make(chan int, 5)

    // Запускаем 3 горутины-воркера
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    // Отправляем задания
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)

    // Считываем результаты
    for r := 1; r <= 5; r++ {
        fmt.Println("Result:", <-results)
    }
}
  • Каналы (channels): Первичный механизм безопасной передачи данных и сигналов между горутинами.
  • Мьютексы (mutex) из пакета sync: Для защиты критических секций при необходимости использования общей памяти (sync.Mutex, sync.RWMutex).
  • WaitGroups и Once: Для координации групп горутин (sync.WaitGroup) и гарантированного однократного выполнения (sync.Once).

Сравнение с многопроцессностью (Multiprocessing)

КритерийМногопоточность (Threads)Многопроцессность (Processes)
ИзоляцияМинимальная, потоки разделяют память процесса.Полная, процессы имеют независимые адресные пространства.
СозданиеБыстрое и легковесное (в модели Go).Более медленное и ресурсоёмкое.
КоммуникацияБыстрая (общая память или каналы в Go).Медленная (IPC: сокеты, файлы, shared memory).
СтабильностьОшибка в одном потоке может убить весь процесс.Ошибка в процессе не затрагивает другие процессы.

Итог

Многопоточность — фундаментальная концепция для создания эффективных, отзывчивых и высоконагруженных приложений. В Go она реализована через инновационную модель goroutines + channels, которая значительно снижает сложность написания параллельного кода и минимизирует традиционные проблемы синхронизации, делая разработку многопоточных программ более безопасной и удобной. Правильное использование горутин, каналов и средств синхронизации из пакета sync позволяет полностью раскрыть потенциал современных многопроцессорных систем.