Совместное использование объекта только для чтения между потоками в Rust? [Дубликат]

Ниже будут возвращены имена внешних ключей в текущей базе данных, которые отключены, т.е. WITH NOCHECK

. Для SQL Server 2005/2008:

select * from sys.foreign_keys where is_disabled=1

В ответе было высказано некоторое мнение о различии между отключенными & amp; не доверяют. Что ниже объясняет differnce Вот некоторый код, чтобы прояснить разницу между is_disabled и amp; isnotrusted.

-- drop table t1
-- drop table t2
create table t1(i int not null, fk int not null)
create table t2(i int not null)
-- create primary key on t2
alter table t2
add constraint pk_1 primary key (i)
-- create foriegn key on t1
alter table t1
add constraint fk_1 foreign key (fk)
    references t2 (i)
--insert some records
insert t2 values(100)
insert t2 values(200)
insert t2 values(300)
insert t2 values(400)
insert t2 values(500)
insert t1 values(1,100)
insert t1 values(2,100)
insert t1 values(3,500)
insert t1 values(4,500)
----------------------------
-- 1. enabled and trusted
select name,is_disabled,is_not_trusted from sys.foreign_keys
GO

-- 2. disable the constraint
alter table t1 NOCHECK CONSTRAINT fk_1
select name,is_disabled,is_not_trusted from sys.foreign_keys
GO

-- 3. re-enable constraint, data isnt checked, so not trusted.
-- this means the optimizer will still have to check the column
alter table  t1 CHECK CONSTRAINT fk_1 
select name,is_disabled,is_not_trusted from sys.foreign_keys
GO

--4. drop the foreign key constraint & re-add 
-- it making sure its checked
-- constraint is then enabled and trusted
alter table t1  DROP CONSTRAINT fk_1
alter table t1 WITH CHECK 
add constraint fk_1 foreign key (fk)
    references t2 (i)
select name,is_disabled,is_not_trusted from sys.foreign_keys
GO


--5. drop the foreign key constraint & add but dont check
-- constraint is then enabled, but not trusted
alter table t1  DROP CONSTRAINT fk_1
alter table t1 WITH NOCHECK 
add constraint fk_1 foreign key (fk)
    references t2 (i)
select name,is_disabled,is_not_trusted from sys.foreign_keys
GO

is_disabled означает, что ограничение отключено

isnottrusted означает, что SQL Server не уверен, что столбец был проверен на таблицу внешнего ключа.

Таким образом, нельзя предположить, что повторное включение ограничения внешнего ключа будет оптимизировано. Чтобы оптимизатор доверял столбцу, лучше всего отказаться от ограничения внешнего ключа & amp; заново создайте его с помощью опции WITH CHECK (4.)

11
задан Shepmaster 3 August 2017 в 18:13
поделиться

1 ответ

Поддержка потоков в стандартной библиотеке позволяет созданным потокам пережить поток, который их создал; это хорошая вещь! Однако, если вы должны передать ссылку на выделенную стекю переменную на один из этих потоков, нет гарантии, что переменная будет по-прежнему действительной к моменту выполнения потока. На других языках это позволит потоку получить доступ к недопустимой памяти, создавая кучу проблем с безопасностью памяти.

К счастью, мы не ограничиваемся стандартной библиотекой. По меньшей мере, два ящика обеспечивают потоки с ограниченной областью - потоки, которые гарантированно выходят до того, как закончится определенный охват. Они могут гарантировать, что переменные стека будут доступны для всей длительности потока:

Есть также ящики, которые абстрагируют детали нижнего уровня «потоков», но позволяют достичь ваших целей:

Вот примеры каждого из них. Каждый пример порождает несколько потоков и мутирует локальный вектор на месте без блокировки, нет Arc и никакого клонирования. Обратите внимание, что мутация имеет вызов sleep, чтобы помочь проверить, что вызовы происходят параллельно.

Вы можете расширить примеры, чтобы поделиться ссылкой на любой тип, который реализует Sync , например Mutex или Atomic*. Однако использование [

scoped-threadpool

extern crate scoped_threadpool;
use scoped_threadpool::Pool;

use std::thread;
use std::time::Duration;

fn main() {
    let mut vec = vec![1, 2, 3, 4, 5];
    let mut pool = Pool::new(vec.len() as u32);

    pool.scoped(|scoped| {
        for e in &mut vec {
            scoped.execute(move || {
                thread::sleep(Duration::from_millis(1000));
                *e += 1;
            });
        }
    });

    println!("{:?}", vec);
}

crossbeam

extern crate crossbeam;

use std::thread;
use std::time::Duration;

fn main() {
    let mut vec = vec![1, 2, 3, 4, 5];

    crossbeam::scope(|scope| {
        for e in &mut vec {
            scope.spawn(move || {
                thread::sleep(Duration::from_millis(1000));
                *e += 1;
            });
        }
    });

    println!("{:?}", vec);
}

rayon

extern crate rayon;

use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
use std::{thread, time::Duration};

fn main() {
    let mut vec = vec![1, 2, 3, 4, 5];

    vec.par_iter_mut().for_each(|e| {
        thread::sleep(Duration::from_millis(1000));
        *e += 1;
    });

    println!("{:?}", vec);
}

клиент должен подключить соединение в Arc, когда он является внутренним для библиотеки, что этот код распараллелен

Возможно, вы можете лучше скрыть свой параллелизм? Не могли бы вы принять регистратор и затем обернуть его в Arc / Mutex, прежде чем передавать его в свои потоки?

11
ответ дан Shepmaster 15 August 2018 в 14:46
поделиться
  • 1
    Большое спасибо за ваш ответ! Моим решением было сделать реализацию Logger Clone и иметь поле с типом Arc<Mutex<Connection>>. Затем пользователь может передать клон регистратора в резьбовой код. Пользователь не может передать право собственности на Connection на код с резьбой (пользователю это нужно для других целей), поэтому я не вижу, чтобы для многопоточного кода удобно использовать Arc и бокс на от имени пользователя. – Ned Ruggeri 24 September 2015 в 22:38
Другие вопросы по тегам:

Похожие вопросы: