【问题标题】:Selectively Enforcing Synchronization to Facilitate Maximum Concurrency有选择地强制同步以促进最大并发
【发布时间】:2015-01-03 08:24:57
【问题描述】:

这就是我想要用 Java 做的事情:

while(writeSetsIntersect()) {
    wait();
}    
doStuff    
notifyAll();

这就是我卡住的地方:doStuff 如果两个线程写入不同的变量,则可以同时执行,即它们具有不相交的写入集。如果写集相交,线程需要交替。所以我不能简单地将doStuff 放在同步块中,因为它并不总是(并且可能永远不会)需要。

我可以锁定写集中的项目,但是如果两个具有相交写集的线程在同一个锁上等待,可能会发生死锁。如:

Lock[] locks = new Lock[allAvailableVariables.length];
public void getLocks() {
    for(i = 0; i < allAvailableVariables.length; i++)
        if(i is in writeSet)
            locks[i].lock();
}

避免这种情况的最简单方法(据我所知)是同步获取写入集中的锁。但是,如果具有相交写入集的两个线程争相进入同步块,则具有与其他两个不相交的写入集的线程将不得不等到它们离开同步块。

我想我可以只拥有一个自旋锁,但如果可能的话我想避免这种情况,因为评估写入集是否相交可能会很昂贵。

这有意义吗?

【问题讨论】:

    标签: java multithreading concurrency synchronization wait


    【解决方案1】:

    看起来你想使用锁排序。

    将锁按某种自然顺序排序。然后依次锁定每个。

    假设您有锁aba &lt; b。如果两个线程想同时锁定ab,它们将首先锁定a。因此,您不会遇到这样的情况:一个线程已锁定 b 并在 a 上被阻塞,而另一个线程已锁定 ab 上被阻塞。

    【讨论】:

    • 如果您无法提前知道需要哪些锁(例如,在doStuff() 进行到一半时,您会发现需要新锁)。在这种情况下,一种选择是尝试通过tryLock() 获取锁。如果成功了,那就太好了。如果没有,你就解开一切,撤销所有工作,然后用你需要的锁重试。
    • @yshavit 当然。有大量关于软件事务内存问题的文献。
    猜你喜欢
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-07
    • 2014-09-15
    • 2018-02-26
    相关资源
    最近更新 更多