Разберете подхода на Rust към едновременността, който се основава на концепцията за „безстрашна едновременност“.

Паралелността е способността на една програма да изпълнява множество задачи едновременно на едно и също процесорно ядро. Едновременните задачи се изпълняват и завършват в припокриващо се време без определен ред, за разлика от паралелизма, където различни задачи или подзадачи на една и съща задача се изпълняват едновременно на хардуер с множество процесори.

Rust се отличава със своите характеристики за производителност и поддръжка за едновременност по безопасен и ефективен начин. Подходът на Rust към паралелността се основава на концепцията за „безстрашна паралелност“, където езикът има за цел да улесни безопасното писане паралелен код чрез своята система за собственост и заемане, която налага стриктни правила по време на компилиране, за да предотврати следи на данни и гарантира памет безопасност.

Разбиране на паралелността в Rust

Rust предоставя няколко примитиви за паралелност за писане на паралелни програми, включително нишки, предаване на съобщения, мутекси, атомни типове и async/await за асинхронно програмиране.

instagram viewer

Ето общ преглед на примитивите за паралелност на Rust:

  1. нишки: Rust предоставя a std:: нишка модул в стандартната си библиотека за създаване и управление на нишки. Можете да създавате нови теми с нишка:: хайвер функция. The нишка:: хайвер приема затваряне, съдържащо кода за изпълнение. Можете също така да изпълнявате нишки, които могат да работят паралелно, а Rust предоставя примитиви за синхронизиране, за да координира тяхното изпълнение. Проверката на заеми гарантира, че препратките не водят до неочаквано поведение.
  2. Преминаване на съобщения: Моделът за едновременност на Rust поддържа предаване на съобщения между нишки. Ще използвате каналите, внедрени чрез std:: sync:: mpsc модул за предаване на съобщения. Каналът се състои от предавател (Подател) и приемник (Приемник). Нишките могат да изпращат съобщения през предавателя и да ги получават през приемника. Това осигурява безопасен и синхронизиран начин за комуникация между нишките.
  3. Мутекси и атомни типове: Rust предоставя примитиви за синхронизация, включително мютексове (std:: sync:: Mutex) и атомни типове (std:: sync:: atomic), за да осигури изключителен достъп до споделяне на данни. Мутексите позволяват на множество нишки да имат достъп до данни едновременно, като същевременно предотвратяват състезания за данни. Атомните типове предоставят атомарни операции върху споделени данни, като например увеличаване на брояч, без да се изисква изрично заключване.
  4. Async/Await и фючърси: Руст асинхронен/изчакайте синтаксисът предоставя функционалност за писане на асинхронен код, който можете да изпълнявате едновременно. Асинхронните програми се справят ефективно с I/O-обвързани задачи, позволявайки на програмите да изпълняват други задачи, докато чакат други I/O операции. на Руст асинхронен/изчакайте синтаксисът се основава на фючърси и можете да ги захранвате с async-std или токио библиотеки за изпълнение.

Нишките Rust са леки и липсата на допълнителни разходи по време на изпълнение ги прави подходящи за приложения с висока производителност. Примитивите за паралелност на Rust се интегрират безпроблемно с множество библиотеки и рамки за различни нужди от паралелност.

Как да използвате Spawn Threads в Rust

Ще използвате std:: нишка модул за създаване на нишки. The std:: thread:: spawn функцията ви позволява да създадете нова нишка, която ще работи едновременно с основната нишка или други съществуващи нишки във вашата програма.

Ето как можете да създадете нишка с std:: thread:: spawn функция:

използване std:: нишка;

fnосновен() {
// Създаване на нова нишка
позволявам thread_handle = thread:: spawn(|| {
// Кодът, изпълнен в новата нишка, отива тук
println!("Здравейте от новата тема!");
});

// Изчакайте заредената нишка да завърши
thread_handle.join().unwrap();

// Кодът, изпълнен в основната нишка, продължава тук
println!(„Здравейте от основната тема!“);
}

The основен функцията създава нова нишка с нишка:: хайвер функция чрез предаване на затваряне, съдържащо кода за изпълнение в нишката (в този случай затварянето е анонимна функция). Затварянето отпечатва съобщение, което показва, че новата нишка работи.

The присъединяване метод на нишка_ръкохватка позволява на основната нишка да изчака заредената нишка да завърши изпълнението. Чрез обаждане присъединяване, функцията гарантира, че основната нишка изчаква заредената нишка да завърши, преди да продължи.

Можете да създадете няколко нишки и да използвате цикъл или друг Структура за контрол на ръждата за създаване на множество затваряния и хвърляне на нишки за всяко.

използване std:: нишка;

fnосновен() {
позволявам брой_нишки = 5;

позволяваммут нишки_ръкохватки = vec![];

за аз в0..num_threads {
позволявам thread_handle = thread:: spawn(ход || {
println!(„Здравейте от нишката {}“, i);
});
thread_handles.push (thread_handle);
}

за дръжка в thread_handles {
handle.join().unwrap();
}

println!(„Всички нишки са завършени!“);
}

Цикълът for ражда пет нишки, всяка с присвоен уникален идентификатор аз с променливата на цикъла. Затварянията улавят стойността на аз с ход ключова дума, която трябва да избягвате проблеми със собствеността, и нишки_ръкохватки вектор съхранява нишките за по-късно в присъединяване цикъл.

След като зареди всички нишки, the основен функцията итерира над нишки_ръкохватки вектор, разговори присъединяване на всеки манипулатор и чака всички нишки да се изпълнят.

Предаване на съобщения през канали

Можете да предавате съобщения през нишки с канали. Rust предоставя функционалност за предаване на съобщения в std:: sync:: mpsc модул. Тук, mpsc означава „множество производители, един потребител“ и позволява комуникация между множество нишки чрез изпращане и получаване на съобщения през канали.

Ето как внедрявате предаване на съобщения през канали за комуникация между нишки във вашите програми:

използване std:: sync:: mpsc;
използване std:: нишка;

fnосновен() {
// Създаване на канал
позволявам (изпращач, получател) = mpsc:: канал();

// Създаване на нишка
нишка:: spawn(ход || {
// Изпратете съобщение през канала
sender.send(„Здравейте от темата!“).unwrap();
});

// Получаване на съобщението в главната нишка
позволявам получено_съобщение = receiver.recv().unwrap();
println!(„Получено съобщение: {}“, получено_съобщение);
}

The основен функция създава канал с mpsc:: канал() който връща a изпращач и а приемник. The изпращач изпраща съобщения до приемник който получава съобщенията. The основен функцията продължава да създава нишки и да премества собствеността върху Подател до затваряне на резбата. Вътре в затварянето на резбата, на sender.send() функцията изпраща съобщение през канала.

The receiver.recv() функцията получава съобщението, като спира изпълнението, докато нишката не получи съобщението. The основен функцията отпечатва съобщението на конзолата след успешно получаване на съобщение.

Имайте предвид, че изпращането на съобщение през канала поглъща подателя. Ако трябва да изпратите съобщения от множество нишки, можете да клонирате подателя с sender.clone() функция.

Освен това, mpsc модул предоставя други методи като try_recv(), който без блокиране се опитва да получи съобщение, и iter(), което създава итератор върху получените съобщения.

Преминаването на съобщения през канали осигурява безопасен и удобен начин за комуникация между нишките, като същевременно се избягват състезания за данни и се гарантира правилна синхронизация.

Моделът за собственост и заемане на Rust гарантира безопасност на паметта

Rust съчетава собственост, заемане и проверка на заеми, за да осигури стабилна, безопасна рамка за едновременно програмиране.

Инструментът за проверка на заеми действа като предпазна мрежа, като открива потенциални проблеми по време на компилиране, вместо да разчита на проверки по време на изпълнение или събиране на боклук.