java - 确定同步范围?

标签 java multithreading concurrency theory

为了提高我对并发问题的理解,我正在研究以下场景(编辑:我已将示例从列表更改为运行时,这更接近我正在尝试的) :

public class Example {
    private final Object lock = new Object();
    private final Runtime runtime = Runtime.getRuntime();
    public void add(Object o) { 
        synchronized (lock) { runtime.exec(program + " -add "+o); } 
    }
    public Object[] getAll() { 
        synchronized (lock) { return runtime.exec(program + " -list "); }
    }
    public void remove(Object o) { 
        synchronized (lock) { runtime.exec(program + " -remove "+o); } 
    }
}

就目前而言,每个方法在独立使用时都是线程安全的。现在,我想弄清楚的是如何处理调用类希望调用的位置:

for (Object o : example.getAll()) {
    // problems if multiple threads perform this operation concurrently
    example.remove(b); 
}

但如前所述,无法保证调用 getAll() 和调用 remove() 之间的状态一致。如果多个线程调用它,我就会遇到麻烦。所以我的问题是 - 我应该如何让开发人员以线程安全的方式执行操作?理想情况下,我希望以一种让开发人员难以避免/错过的方式强制执行线程安全,但同时实现起来并不复杂。到目前为止,我可以想到三个选项:

A: 将锁设置为“this”,这样调用代码就可以访问同步对象,然后调用代码可以包装代码块。缺点:难以在编译时执行:

synchronized (example) {
    for (Object o : example.getAll()) {
        example.remove(b);
    }
}

B:将合并后的代码放入 Example 类中 - 并从能够优化实现中获益,就像在本例中一样。缺点:添加扩展的痛苦,以及可能混合不相关的逻辑:

public class Example {
   ...
   public void removeAll() { 
       synchronized (lock) { Runtime.exec(program + " -clear"); } 
   }
}

C:提供一个闭包类。缺点:过多的代码,可能过于慷慨的同步块(synchronized block),实际上可能使死锁更容易:

public interface ExampleClosure {
    public void execute(Example example);
}
public Class Example {
    ...
    public void execute(ExampleClosure closure) { 
        synchronized (this) { closure.execute(this); } 
    }
}

example.execute(new ExampleClosure() {
        public void execute(Example example) { 
            for (Object o : example.getAll()) {
                example.remove(b);
            }
        }
    }
);

有什么我想念的吗?应该如何限定同步范围以确保代码是线程安全的?

最佳答案

使用通过 API 公开的 ReentrantReadWriteLock。这样,如果有人需要同步多个 API 调用,他们可以在方法调用之外获取锁。

关于java - 确定同步范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3831315/

相关文章:

c# - HttpWebRequest:无法连接到远程服务器

c - 与共享变量并行运行 2 个线程

java - 了解链式 CompletableFuture 的并行执行

java - 将第一个 CompletableFuture 的结果传递给链上的其他 CompletableFuture

java - 如何使用 Hibernate HQL 或 Criteria 内部连接两个表?

java - 在jtable的所有行中导入mysql数据库的最后一行(Java Swing)

java - Keycloak 给出无效的重定向 uri 错误

c - 使用 fork() 时收割子进程

c - 如何在微 Controller 中实现多任务?

php - 如何修复 PHP MySQL 中达到 508 资源限制