В чем разница между процессом и потоком (тредом)?

Ответ

Процесс и поток (тред) — это фундаментальные концепции в операционных системах для выполнения кода, но они имеют ключевые различия.

Процесс:

  • Определение: Экземпляр запущенной программы.
  • Изоляция: Каждый процесс имеет собственное, изолированное адресное пространство памяти, файловые дескрипторы, и другие системные ресурсы.
  • Стоимость создания: Создание процесса — «тяжелая» операция (например, через системный вызов fork()), так как требует выделения и копирования ресурсов.
  • Взаимодействие: Процессы взаимодействуют друг с другом через механизмы межпроцессного взаимодействия (IPC), такие как каналы (pipes), сокеты или общая память.

Поток (Тред):

  • Определение: Легковесная единица выполнения внутри процесса.
  • Изоляция: Потоки разделяют адресное пространство и ресурсы своего родительского процесса (память, открытые файлы). У каждого потока есть свой собственный стек вызовов и состояние регистров.
  • Стоимость создания: Создание потока — «легкая» операция, так как не требует копирования ресурсов процесса.
  • Взаимодействие: Потоки могут взаимодействовать напрямую через общую память, что гораздо быстрее, чем IPC, но требует механизмов синхронизации (мьютексы, семафоры) для избежания состояния гонки.

Контекст Go:
В Go основной единицей конкурентности является горутина, а не системный поток. Горутины еще более легковесны, чем потоки ОС. Go runtime управляет пулом системных потоков и мультиплексирует (распределяет) множество горутин на меньшее количество потоков. Это позволяет создавать сотни тысяч и даже миллионы горутин в одном процессе.

package main

import (
    "fmt"
    "os/exec"
    "sync"
    "time"
)

func main() {
    // Пример создания нового ПРОЦЕССА
    // Запускаем внешнюю команду `ls -l`, которая выполняется в отдельном процессе.
    cmd := exec.Command("ls", "-l")
    fmt.Println("Запуск нового процесса...")
    output, err := cmd.Output()
    if err != nil {
        fmt.Println("Ошибка запуска процесса:", err)
    } else {
        fmt.Printf("Вывод процесса:n%s", output)
    }

    // Пример создания ПОТОКА (через горутину в Go)
    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
        defer wg.Done()
        fmt.Println("nЭто сообщение из горутины (легковесного потока)")
    }()

    // Ожидаем завершения горутины, чтобы главная программа не завершилась раньше.
    wg.Wait()
}