【问题标题】:ReadWriteLock writelock saturatedReadWriteLock 写锁饱和
【发布时间】:2017-07-15 10:18:47
【问题描述】:

我遇到了 Writer 线程在没有获得锁的情况下被饿死的问题。 请看下面的代码。如果我尝试使用tryLock() 获取锁作为读锁,则写入器进程将变得饥饿并且永远无法写入。即使公平,编写器进程也会完全饿死并且永远不会执行。相反,如果我只尝试reader.readLock(),那么编写器进程将能够获得锁。

如果我遗漏了什么,请告诉我,编写器进程线程即使设置为高优先级,它也永远不会获得锁并且会卡住等待锁。

谁能告诉我是否可以使用trylock()ReadWriteLocks

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.*;

class ReadWrite{
    private int a, j=0,k =0;

    private final ReentrantReadWriteLock asd = new ReentrantReadWriteLock();
    private final Lock readlock = asd.readLock();
    private final Lock writelock = asd.writeLock();
    ReadWrite(){
        a = 0 ;
    }
    ReadWrite(int a){
        this.a = a;
    }
    public int read() {

        try {
            if (readlock.tryLock())
            {
                //readlock.lock();

                k = k + 1;
                if (k%100000==0) {
                    System.out.println("read " + k + " times ==> Written " + j + " times");

                }

                readlock.unlock();

                return a;
            }



        }
        catch(Exception E) {
            System.out.println(E);
            return a;
        }
        return 0;

    }
    public void write(int a) {
        int k = 9;
        try {
            writelock.lock();
                //writelock.lock();
                this.a = a;
                k = 0;
                j = j + 1;
                System.out.println("Acquored");
        }
        catch(Exception E) {
            System.out.println(E);
        }
        finally {
            if (k == 0 )
                writelock.unlock();
        }
    }

}

class reader implements Runnable{
    ReadWrite a;
    reader(Object b){
        a = (ReadWrite) b;
    }
    public void run() {
        while(true) {

            try{a.read();
                //Thread.sleep(100);
            }
            catch(Exception E) {

            }
        }
    }
}
class writer implements Runnable{
    ReadWrite a;
    writer(Object b){
        a = (ReadWrite) b;
    }
    public void run() {
        //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        while(true) {
            try {
                //Thread.sleep(1);
            }
            catch(Exception E) {

            }
            a.write((int) Math.ceil(Math.random()*100));
        }
    }
}
class Practice{
    public static void main(String args[]) {
        ReadWrite a = new ReadWrite();
        System.out.println("Invoking Write Thread");
        ExecutorService asd = Executors.newFixedThreadPool(100);
        asd.execute(new writer(a));

        for (int i = 0 ; i < 98 ; i ++)
            asd.execute(new reader(a));

    }
}

【问题讨论】:

  • 您错误地使用了锁定/解锁程序 - 在编写器中您尝试获取锁定,而在阅读器中您没有。可怕的无限循环没有任何中断。你能解释一下你的代码的目的是什么吗?

标签: java multithreading readwritelock reentrantreadwritelock


【解决方案1】:

在这种不公平的情况下使用ReentrantReadWriteLock 将永远不会起作用:太多的读取器线程只会使写入器线程饿死。

为了公平起见,作者线程将偶尔获得写作机会。

但是,在您的代码中将 ReentrantReadWriteLock 设置为 fair 被证明是徒劳的。这是刺痛的地方:您的读者不使用lock(),而是使用tryLock()。因此,他们永远不会排队等待获得锁,如果它可用,他们就会得到它。而且通过不排队(内部在ReentrantReadWriteLock),他们规避了公平政策。

注意 tryLock() 上的 javadoc ReadLock 对象:

仅当调用时另一个线程没有持有写锁时才获取读锁。 如果写锁没有被另一个线程持有,则获取读锁,并立即返回值为 true。 即使此锁已设置为使用公平排序策略,调用 tryLock() 也会立即获取读取锁(如果可用),无论其他线程当前是否正在等待读取锁.这种“闯入”行为在某些情况下可能很有用,即使它破坏了公平性。如果您想尊重此锁的公平设置,请使用几乎等效的 tryLock(0, TimeUnit.SECONDS)(它也检测中断)。

如果写锁被另一个线程持有,则此方法将立即返回值为 false。

(强调我的)

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 2015-05-09
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    相关资源
    最近更新 更多