java - 我可以使用空锁对象同步 2 个线程的操作吗?

标签 java multithreading synchronization

我在一个应用程序中有 2 个独立的线程,用于执行一些图论模拟(使用 Java2D),其中一个线程每秒执行约 60 次,其任务是渲染。另一个每秒执行约 30 次并进行一些计算。

这两个线程共享资源。具体来说,他们共享他们迭代的集合。当这两个线程同时访问集合时就会出现问题。 (一个是尝试渲染其中的对象,而另一个是修改集合)。这会导致 ConcurrentModificationException。我已经尝试了一些解决方案,我发现其中一个可以正常工作(并且很容易实现)的解决方案是使用一个空对象,线程切换时保持锁定。

像这样(示例代码):

public class Question {

static Object syncObject;

public static void main(String []Args) {

    syncObject = new Object();

    Runnable rendering = new Runnable() { //called 60 times a second
        public void run() {
            synchronized(syncObject) {
                //doRendering
            }

        }
    };
    Runnable calculations = new Runnable() { //called 30 times a second
        public void run() {
            synchronized(syncObject) {
                //doModifications
            }       
        }
    };

    Thread t1 = new Thread(rendering);
    Thread t2 = new Thread(calculations);
    t1.start();
    t2.start();
    }
}

现在,这似乎工作正常。这样我就不必同步我正在使用的每个资源,这些资源可能在渲染以及“逻辑”计算更新时进行修改。

但我觉得这不是一个很好的解决方案。所以我想问这是否可以接受和/或是否有更合适的解决方案。 (除非我所做的完全错误)

此外,我不想重写我已经工作了一段时间的现有代码的一半。

最佳答案

当“粗略”锁合适时,您在上面实现的全局锁是一个很好的解决方案。我觉得它很符合你的情况。

要改进它,您应该确保全局锁是不可变的。

private static final Object syncObject = new Object();

这种方法的局限性在于您本质上是序列化对图的所有访问。这将并发的潜力限制为一次只有一个。因此,在多 CPU 计算机上,CPU 会闲置,而渲染和计算工作可能会花费很长时间。优点是实现简单,并且可以安全地从不同线程访问。

其他实现起来更复杂的选项是:1)使用多个细粒度锁,2)研究“无锁算法”或3)使用数据结构的变异/发布方法实现“不可变”。

以下引用文献讨论了粗粒度锁和细粒度锁:http://fileadmin.cs.lth.se/cs/education/eda015f/2013/herlihy4-5-presentation.pdf

无锁算法的正确实现需要非常复杂的工作,并且不适用于所有情况。底漆可以阅读 here .

选项 3,使用不可变数据结构有很多优点(和一些限制)。这意味着图表一旦创建就无法更改。通过创建新图会发生突变;为了减少内存开销,允许重用图表的某些部分。这意味着渲染可以获取图形的副本,并在与改变图形的计算完全隔离的情况下进行渲染。当突变完成时,可以使用 AtomicReference 使更新后的图形可供渲染器使用。缺点是它需要更多的对象分配和更复杂的变异算法,但是它受益于允许“读取器”线程与单个更改器(mutator)线程并行工作。欲了解更多详情,请参阅persistent vs immutable data structure , https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.htmlHow does concurrency using immutable/persistent types and data structures work? .

关于java - 我可以使用空锁对象同步 2 个线程的操作吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51267932/

相关文章:

java - Android - 使 Activity 根据点击的内容显示不同的内容

java - 使用 QueryDSL 和 Mongo 转换映射值类型

java - Java 线程中的实例变量(对象,非原始变量)缓存

MongoDB 同步开发和生产数据库

java - 如何协调多个类对私有(private)对象的同步

java - Java 中的静态泛型字段

java - Hibernate Spatial 创建几何对象

Java线程方法与 block 同步

java - Spring框架在高负载下使用@Async方法

java - Thread.isInterrupted 总是返回 false