如何理解“不公平” ReentrantReadWriteLock的模式? [英] How to understand the "non-fair" mode of ReentrantReadWriteLock?

查看:142
本文介绍了如何理解“不公平” ReentrantReadWriteLock的模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ReentrantReadWriteLock具有公平且不公平(默认)的模式,但该文档对我来说很难理解。

ReentrantReadWriteLock has a fair and non-fair(default) mode, but the document is so hard for me to understand it.

我如何理解它?如果有一些代码示例来演示它,那就太棒了。

How can I understand it? It's great if there is some code example to demo it.

更新

如果我有一个写线程,并且有很多阅读线程,哪种模式更好用?如果我使用非公平模式,写作线程是否有可能获得锁定?

If I have a writing thread, and many many reading thread, which mode is better to use? If I use non-fair mode, is it possible the writing thread has little chance to get the lock?

推荐答案

非公平意味着当准备好通过新线程获取锁时,锁不能保证谁获得锁的公平性(假设当时有多个线程请求锁)。换句话说,可以想象一个线程可能会持续缺乏,因为其他线程总是设法随意获取锁定而不是它。

Non-fair means that when the lock is ready to be obtained by a new thread, the lock gives no guarantees to the fairness of who obtains the lock (assuming there are multiple threads requesting the lock at the time). In other words, it is conceivable that one thread might be continuously starved because other threads always manage to arbitrarily get the lock instead of it.

公平模式更像是先来先服务,其中线程保证某种程度的公平性,以便他们以公平的方式获得锁定(例如,在开始等待很长时间的线程之前)。

Fair mode acts more like first-come-first-served, where threads are guaranteed some level of fairness that they will obtain the lock in a fair manner (e.g. before a thread that started waiting long after).

这是一个示例程序,用于演示锁的公平性(因为锁定的锁定请求是先来的,首先是提供服务)。当 FAIR = true (线程始终按顺序提供)与 FAIR = false (线程有时不按顺序服务)。

Here is an example program that demonstrates the fairness of locks (in that write lock requests for a fair lock are first come, first served). Compare the results when FAIR = true (the threads are always served in order) versus FAIR = false (the threads are sometimes served out of order).

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class FairLocking {

    public static final boolean FAIR = true;
    private static final int NUM_THREADS = 3;

    private static volatile int expectedIndex = 0;

    public static void main(String[] args) throws InterruptedException {
        ReentrantReadWriteLock.WriteLock lock = new ReentrantReadWriteLock(FAIR).writeLock();

        // we grab the lock to start to make sure the threads don't start until we're ready
        lock.lock();

        for (int i = 0; i < NUM_THREADS; i++) {
            new Thread(new ExampleRunnable(i, lock)).start();

            // a cheap way to make sure that runnable 0 requests the first lock
            // before runnable 1
            Thread.sleep(10);
        }

        // let the threads go
        lock.unlock();
    }

    private static class ExampleRunnable implements Runnable {
        private final int index;
        private final ReentrantReadWriteLock.WriteLock writeLock;

        public ExampleRunnable(int index, ReentrantReadWriteLock.WriteLock writeLock) {
            this.index = index;
            this.writeLock = writeLock;
        }

        public void run() {
            while(true) {
                writeLock.lock();
                try {
                    // this sleep is a cheap way to make sure the previous thread loops
                    // around before another thread grabs the lock, does its work,
                    // loops around and requests the lock again ahead of it.
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    //ignored
                }
                if (index != expectedIndex) {
                    System.out.printf("Unexpected thread obtained lock! " +
                            "Expected: %d Actual: %d%n", expectedIndex, index);
                    System.exit(0);
                }

                expectedIndex = (expectedIndex+1) % NUM_THREADS;
                writeLock.unlock();
            }
        }
    }
}



编辑(再次)



关于你的更新,非公平锁定并不是说线程有可能获得锁定的可能性很小,而是有可能线程必须稍等一点的可能性很小。

Edit (again)

Regarding your update, with non-fair locking it's not that there's a possibility that a thread will have a low chance of getting a lock, but rather that there's a low chance that a thread will have to wait a bit.

现在,通常随着饥饿期的增加,实际发生这段时间的概率会降低......就像连续10次翻转硬币头一样,连续9次翻转硬币头的可能性较小。

Now, typically as the starvation period increases, the probability of that length of time actually occuring decreases...just as flipping a coin "heads" 10 consecutive times is less likely to occur than flipping a coin "heads" 9 consecutive times.

但如果多次等待的选择算法线程是非随机化的东西,比如按字母顺序排在第一位的线程总是得到锁定然后你可能会遇到一个真正的问题,因为随着线程变得越来越饿,概率不一定会减少...如果是硬币加权到头10个连续的头基本上与9个一样可能连续的头。

But if the selection algorithm for multiple waiting threads was something non-randomized, like "the thread with the alphabetically-first name always gets the lock" then you might have a real problem because the probability does not necessarily decrease as the thread gets more and more starved...if a coin is weighted to "heads" 10 consecutive heads is essentially as likely as 9 consecutive heads.

我认为在非公平锁定的实施中使用了一些公平的硬币。因此,问题确实变得公平(因此,延迟)与吞吐量相比。使用非公平锁定通常会产生更好的吞吐量,但代价是锁定请求偶尔会出现延迟峰值。哪个更适合您,取决于您自己的要求。

I believe that in implementations of non-fair locking a somewhat "fair" coin is used. So the question really becomes fairness (and thus, latency) vs throughput. Using non-fair locking typically results in better throughput but at the expense of the occasional spike in latency for a lock request. Which is better for you depends on your own requirements.

这篇关于如何理解“不公平” ReentrantReadWriteLock的模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆