我有一个问题,即编写器线程在没有锁定的情况下被饿死。 请查看以下代码。如果我尝试使用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));
}
}
在这种情况下使用ReentrantReadWriteLock
不公平,是行不通的:太多的阅读器线程只会使编写器线程匮乏。
公平地说,作者线程将偶尔有机会写作。
但是,事实证明,在代码中将ReentrantReadWriteLock
设置为公平是徒劳的。刺痛的是:你的读者不使用lock()
,而是tryLock()
。因此,他们永远不会排队等待锁定获取,他们只是在可用时获得它。通过不排队(内部ReentrantReadWriteLock
),他们规避了公平政策。
请注意ReadLock
对象的 javadoc ontryLock()
:
仅当写锁定在调用时未由另一个线程持有时,才获取读锁定。 如果写锁定未由另一个线程持有,则获取读锁定,并立即返回值 true。即使此锁已设置为使用公平排序策略,对 tryLock() 的调用也会立即获取读锁定(如果可用),无论其他线程当前是否正在等待读锁定。这种"吠叫"行为在某些情况下可能很有用,即使它破坏了公平性。如果要遵循此锁的公平性设置,请使用几乎等效的tryLock(0,TimeUnit.SECONDS)(它还检测中断)。
如果写锁定由另一个线程持有,则此方法将立即返回值 false。
(强调我的)