我有下面的代码。随着注释掉的部分,它的工作。当我取消注释这些部分时,它不再编译。
如何调整注释部分以使其工作,即,我想让线程同时访问表达式树。
当我尝试它时,编译器从关于线程安全性的错误开始。
我读过 Rust 的书,知道 C/C++,但还没有完全理解 Rust 类型系统和语义。
use std::thread;
use std::sync::Arc;
pub trait Expr {
fn run(&self) -> i32;
}
pub struct ConstantExpr {
n: i32,
}
impl ConstantExpr {
pub fn new(n: i32) -> Self {
Self { n }
}
}
impl Expr for ConstantExpr {
fn run(&self) -> i32 {
self.n
}
}
pub struct AddExpr {
expr1: Box<Expr>,
expr2: Box<Expr>,
}
impl AddExpr {
pub fn new(expr1: Box<Expr>, expr2: Box<Expr>) -> Self {
Self …Run Code Online (Sandbox Code Playgroud) Hazelcast IMap put 方法获取存储桶或分区或键的锁?
java.util.concurrent.ConcurrentHashMapput 方法获取存储桶上的锁并写入 Map。
而在 Hazelcast IMap 中,这是一种分布式地图实现java.util.concurrent.ConcurrentHashMap,当以下代码由一个 Hazelcast 节点执行时。
imap.put(key, value);
它是否获得了对存储桶、分区或密钥的锁定?请说清楚?我在 hazelcast 文档中的任何地方都没有看到这个问题的答案。
我知道在 vert.x 中,每次我们不需要在处理程序中编写线程安全时,默认的 Verticle 都会在同一个事件循环中运行。
例如,如果我有一个运行 HttpServer 的 Verticle -
public class HttpServerVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
vertx.createHttpServer().requestHandler(req -> {
req.response().putHeader("content-type", "text/html").end("
<html><body><h1>Hello from vert.x!</h1></body></html>");
}).listen(8080);
}
Run Code Online (Sandbox Code Playgroud)
}
保证在任何时候,我的请求处理程序都会在 2 个事件循环中被调用两次(针对 2 个不同的请求)。因此,我不必在我的请求处理程序中处理线程安全。
现在,如果我正在运行 HttpServer verticle 的多个实例 -
DeploymentOptions deploymentOptions = new
DeploymentOptions().setWorker(false).setInstances(10);
vertx.deployVerticle("com.....HttpServerVerticle", deploymentOptions);
Run Code Online (Sandbox Code Playgroud)
我需要注意线程安全吗?多个请求处理程序(最大 = 10)有可能并行运行吗?
我使用 ConcurrentBag 来包含字符串列表。有时它会包含一个副本。
但是我在添加新条目之前检查了它的内容,所以它不应该有重复。
ConcurrentDictionary<string, string> SystemFiles = PopulateSystemFiles();
ConcurrentBag<string> SystemNames = new ConcurrentBag<string>();
Parallel.ForEach(SystemFiles, file =>
{
string name = GetSystemName(file.Value);
if (!SystemNames.Contains(name))
{
SystemNames.Add(name);
}
});
Run Code Online (Sandbox Code Playgroud)
我的假设是 .Contains 方法不是线程安全的。我对么?
c# parallel-processing concurrency multithreading thread-safety
我有以下代码行:
var a_map = make(map[string] []int)
Run Code Online (Sandbox Code Playgroud)
我使用 a_map 变量的部分代码偶尔会引发以下错误:
fatal error: concurrent map read and map write
Run Code Online (Sandbox Code Playgroud)
为了创建一个更健壮的解决方案,一个没有此类错误的解决方案,我想使用一个 sync.Map 而不是通用映射。对此堆栈溢出问题提供的唯一答案启发了我这样做。但是,我不清楚这样做的正确语法。
对于我的第一次尝试,我使用了以下代码行:
var a_map = make(sync.Map[string] []int)
Run Code Online (Sandbox Code Playgroud)
这导致了以下错误:
...syntax error: unexpected ], expecting expression
Run Code Online (Sandbox Code Playgroud)
然后我尝试:
sync_map := new(sync.Map)
var a_map = make(sync_map[string] []int)
Run Code Online (Sandbox Code Playgroud)
这导致了同样的错误:
...syntax error: unexpected ], expecting expression
Run Code Online (Sandbox Code Playgroud) 代码片段:
a = 0
Array.new(50){
Thread.new {
500_000.times { a += 1 }
}
}.each(&:join)
p "a: #{a}"
Run Code Online (Sandbox Code Playgroud)
结果:a = 25_000_000。
据我了解,(MRI) Ruby 使用 GIL,所以只有一个 ruby 线程可以获得 CPU,但是当发生线程切换时,会存储一些 ruby 线程的数据,以便稍后恢复线程。所以,理论上,a += 1可能不是线程安全的。
但上面的结果证明我错了。Ruby 是否具有a+=1原子性?如果为真,哪些操作可以被认为是线程安全的?
考虑以下代码。
public class Test {
private boolean running = false;
public void run() {
running = true;
}
public void test() {
boolean running1 = running;
boolean running2 = running;
System.out.println("running1: " + running1);
System.out.println("running2: " + running2);
}
}
Run Code Online (Sandbox Code Playgroud)
线程 A 调用run(),然后另一个线程 B 调用test()并且不应该有任何发生之前的关系。我知道不能保证线程 B 看到线程 A 所做的更改。但是这个程序的输出有没有可能是:
running1: true
running2: false
Run Code Online (Sandbox Code Playgroud) java concurrency multithreading thread-safety happens-before
我编写了以下函数,它接受一个对象 ( element),在现有向量 ( elements) 中为它腾出空间,并通过添加新对象来更新向量:
void addElement(const ElementType& element) {
if (numElements == elements.size()) {
elements.resize(boost::extents[numElements+1]);
}
elements[numElements] = element;
numElements++;
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能使它对 MPI 线程安全?据我了解,每个线程都知道的大小elements是多少,因此我不明白为什么这个函数不是线程安全的。numElements在此函数外初始化为零,并且是elements向量的大小。
编辑:我使用上面写的函数和 mtx 锁定和解锁如下,但最终elements向量仍然只包含来自第一级的数据。
#pragma omp parallel for collapse(3) schedule(static)
for (long n0 = mgr->startN0; n0 < mgr->startN0 + mgr->localN0; n0++) {
for (int n1 = 0; n1 < ?; n1++) {
for (int n2 = 0; n2 < ?; n2++) {
ElementType element;
std::mutex …Run Code Online (Sandbox Code Playgroud) 我注意到,如果我让一个线程填充一个集合,在 之后的线程末尾join,我会看到该集合按预期填充。
关于 Java 内存模型,这是否总是保证发生?
如果线程将列表中对象的引用存储在 cpu 缓存中怎么办?
在这种情况下,加入后加入线程必须保证看到变化?
final ArrayList<Person> persons = new ArrayList();
Thread myThread = new MyThread(persons);
myThread.start();
myThread.join();
// persons ?
Run Code Online (Sandbox Code Playgroud)
线
public class MyThread extends Thread {
ArrayList<Person> persons;
public MyThread(ArrayList<Person> persons){
this.persons = persons;
}
public void run(){
persons.add(new Person(...))
// add more
}
}
Run Code Online (Sandbox Code Playgroud) 我了解到线程之间通信的一种方法是共享一些原子数据结构。例如:
struct Point {
int const x, y;
};
std::atomic<Point> some_point_in_shared_memory{Point{0, 0}};
Run Code Online (Sandbox Code Playgroud)
尽管Point::operator=(Point const &)被删除,但调用赋值运算符似乎没有问题std::atomic<Point>,如下所示:
some_point_in_shared_memory = Point{1, 2};
Run Code Online (Sandbox Code Playgroud)
如何实施此操作?
我可能会想到的一种解决方案是使用placement new在旧对象之上构造一个新对象,但显然它不是异常安全的。还是因为Point可以简单地复制而没关系?