questions - java multithreading simple example



Как я могу надежно очистить потоки Rust, блокируя IO? (2)

tldr; Фиктивная связь может быть самым простым способом.

(Я предполагаю, что linux как os.)

listener.incoming () вызовет .accept () в TcpListener в методе .next (), и поток будет застревать в вызове accept на os. Он может, насколько мне известно, только добровольно возвращаться в результате попытки подключения или сигнала или если сокет установлен неблокированным.

обработка сигналов, похоже, не поддерживается стандартными библиотеками ржавчины.

Файловый дескриптор сокета, похоже, не доступен в TcpListener, поэтому вы не можете установить его в неблокирующий режим. Также это будет означать опрос, это может быть плохой идеей.

Альтернативой может быть использование mio, поскольку он обеспечивает цикл событий. Вы могли бы либо адаптировать все ваше приложение к циклу событий, и не нужно было делать потоки, или вы могли бы использовать цикл событий для каждого потока, который мог бы блокировать и позволять ему прослушивать дополнительный канал, чтобы вы могли его разбудить, что он может закрыться. Первый, возможно, больше не выполним, в зависимости от того, сколько кода у вас уже есть, а второе - переполнения.

https://src-bin.com

Кажется, что в Rust есть обычная идиома, чтобы создать поток для блокировки ввода-вывода, чтобы вы могли использовать неблокирующие каналы:

use std::sync::mpsc::channel;
use std::thread;
use std::net::TcpListener;

fn main() {
    let (accept_tx, accept_rx) = channel();

    let listener_thread = thread::spawn(move || {
        let listener = TcpListener::bind(":::0").unwrap();
        for client in listener.incoming() {
            if let Err(_) = accept_tx.send(client.unwrap()) {
                break;
            }
        }
    });
}

Проблема в том, что воссоединение таких потоков зависит от того, что порожденный поток «понимает», что принимающий конец канала был удален (т. Е. Вызов send(..) возвращает Err(_) ):

drop(accept_rx);
listener_thread.join(); // blocks until listener thread reaches accept_tx.send(..)

Вы можете сделать фиктивные соединения для TcpListener s и TcpStream s через клон, но они кажутся действительно хакерскими способами очистки таких потоков, и, поскольку это так, я даже не знаю, как взломать, чтобы вызвать блокировку потока на чтение из stdin для присоединения.

Как я могу очистить потоки, подобные этим, или моя архитектура ошибается?


Answer #1

Одно просто не может безопасно отменить поток надежно в Windows или Linux / Unix / POSIX, поэтому он недоступен в стандартной библиотеке Rust.

Вот внутренняя дискуссия об этом .

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

mio доступен для асинхронного кода. Tokio - это ящик более высокого уровня, основанный на mio, который делает запись неблокирующего асинхронного кода еще более прямым.





channel