【问题标题】:java - Own SeqLock implementation, would avoiding spinlock be better?java - 自己的 SeqLock 实现,避免自旋锁会更好吗?
【发布时间】:2013-10-24 22:29:45
【问题描述】:

我创建了自己的简单、紧凑的 ReadWriteLock 实现。第一个在尝试获取读锁时使用自旋锁。如果设置了锁定位,则第二个通过在旋转之前暂时获取写锁来避免自旋锁。这样,它会停止执行,直到写锁被释放。现在我的问题是哪个更有效,更适合常用? (多核和非多核机器)

编辑:它将用于我的 Android 应用程序。所以我必须在提供我需要的 ReadWriteLock 实现的同时保持它的紧凑性。 ReentrantReadWriteLock 对我的应用程序来说很重。另外,谁能推荐一个更好的方法?

编辑:实现细节取自this link

第一种实现如下:

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

public class SpinSeqLock {

    private AtomicLong status = new AtomicLong();
    private ReentrantLock writeLock = new ReentrantLock();

    public long readLock() {
        long current;
        do
            current = status.get();
        while ((current & 1) != 0);
        return current;
    }

    public boolean tryReadUnlock(long previous) {
        return status.get() == previous;
    }

    public void writeLock() {
        writeLock.lock();
        status.incrementAndGet();
    }

    public void writeUnlock() {
        status.incrementAndGet();
        writeLock.unlock();
    }

    public void writeLockInterruptibly() throws InterruptedException {
        writeLock.lockInterruptibly(); // If we get interrupted, do not proceed below!

        // Increment only on successful uninterrupted lock
        status.incrementAndGet();
    }
}

第二种实现如下:

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

public class SemiSeqLock {

    private AtomicLong status = new AtomicLong();
    private ReentrantLock writeLock = new ReentrantLock();

    public long readLock() {
        for (;;) {
            long current = status.get();
            if ((current & 1) == 0)
                return current;
            writeLock.lock(); // Avoids spin lock by halting until lock-acquisition.
            writeLock.unlock();
        }
    }

    ... // Same code as the first one
}

预期的用法是:

读者话题:

for (;;) {
    final long status = seqLock.readLock();
    // ... some read operation ...
    // ... some read operation ...
    if (seqLock.tryReadUnlock(status)) break;
}

作家线程:

seqLock.writeLock();
try {
    // ... some write operation ...
    // ... some write operation ...
} finally {
    seqLock.writeUnlock();
}

有什么更正吗?哪个更好?

【问题讨论】:

  • "I created my own .* lock implementation (in Java)" *颤抖*.

标签: java android performance concurrency readwritelock


【解决方案1】:

你确定

  • 你需要它并且
  • 你能比现有的实现更好吗?

这样的事情很容易出错,比普通程序要多得多。

所以真的要尝试使用现有的锁。

您的锁中至少有一个错误:writeLockInterruptibly 必须使用finally

在性能方面,通过writeLock 在长时间睡觉之前旋转几次可能是明智的。总的来说,我不确定它是否会起作用……但它看起来很有趣。

再一次:首先尝试一些现有的锁,该锁是由在该领域非常聪明和经验丰富的人编写的。

【讨论】:

  • "writeLockInterruptibly 必须使用finally",这样做将允许更新状态编号,如果锁被中断,则状态编号不应增加。奇数锁定写锁。因此,代码按预期工作,不需要 finally 块。
  • '再一次:首先尝试一些现有的锁......',我做了很多。我一直在做一些性能测试。之后,我发现他们正在减慢我的程序。他们中的大多数都有一个问题,即对于 ReadWriteLock,java 说,“底层实现很复杂”,即 ReentrantLocks 在运行测试时运行得更快。
猜你喜欢
  • 1970-01-01
  • 2014-12-29
  • 2011-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多