gpt4 book ai didi

java - 多级锁会导致多线程程序死锁吗?

转载 作者:行者123 更新时间:2023-12-01 17:19:22 24 4
gpt4 key购买 nike

我有一个包含编写者和读者的程序,他们的访问权限由监视器控制。

所以,这应该会挨饿,但我陷入了僵局。我想知道为什么,然后我记得我又放了一个锁,我认为在读取器内部的读取方法中没有必要这样做,以保护我的全局变量免受不一致的影响。我认为这不会导致任何死锁,因为我可以运行线程 10000 次而不会发生任何死锁,但是当我必须进行实验室演示时,我认为它在第 10010 个线程处死锁。我不明白为什么它会这样做。另外,我没想到它会挨饿,但显然它应该挨饿。

我的问题是:那些多级锁是否造成了死锁?如果不是,是什么原因造成的?!

    import java.io.*;
import java.io.IOException;
import java.util.*;

public class Writer extends Thread{

private int number;

public Writer(int number)
{
this.number = number;
}

public int getNumber()
{
return number;
}

public static void Write(String filename){

try {

String content = RandomString();


File f = new File(filename);

if (!f.exists())
{
f.createNewFile();
}


PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("Task1out.txt", true)));
out.println(content);
out.close();


} catch (IOException e) {
e.printStackTrace();
}
}

public static String RandomString(){

String chars = new String("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
int n = chars.length();

String randomString = new String();
Random r = new Random();

for (int i=0; i<100; i++)
{
randomString = randomString + chars.charAt(r.nextInt(n));
}

System.out.println("RandomString() generated: " + randomString);

return randomString;

}



public void run(){

try{

//FileControl fc = new FileControl();

int number = this.getNumber();


for(int i = 0; i <1000; i++) //CHANGE IT TO 1000
{
main.fc.WriterEntry(number);

//write file random characters (must append)

Write("Task1out.txt");

main.fc.WriterExit(number);

}
} catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}

}


}

这是作家类。

    import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;



public class Reader extends Thread{


private int number;

public Reader(int number)
{
this.number = number;
}


public int getNumber()
{
return number;
}

public static synchronized void Read(String filename)throws InterruptedException{

BufferedReader br = null;





main.lock.lock(); //lock
try{




try {


String line;
char[] chars = new char[100];
int readIndex2 = 0;
int addToIndex = 0;



br = new BufferedReader(new FileReader(filename));


int initialReadIndex = main.getIndex();




System.out.println("initial read index: " + initialReadIndex);

while ((line = br.readLine()) != null && readIndex2 < initialReadIndex+100 && addToIndex < 100) {

for(int i = 0; i< 100; i++)
{
if (initialReadIndex == readIndex2 || initialReadIndex < readIndex2)
{

if(line.length() > addToIndex)
{




chars[i] = line.charAt(i);
addToIndex++;
}


}
else
{
readIndex2++;
}
}
System.out.println(chars);
}

if(line == null)
{
System.out.println("nothing to read");
}



main.incrementIndex(addToIndex);


System.out.println("current read index: " + (initialReadIndex + addToIndex));





} catch (IOException e) {
e.printStackTrace();
System.out.println("buffered reader exception");
} finally {


try {


if (br != null)
{

br.close();
}
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("exception during closing");
}
}
}finally{
main.lock.unlock(); //lock

}

}


public void run(){

try{


//FileControl fc = new FileControl();


int number = this.getNumber();


for(int i = 0; i <1000; i++) //CHANGE IT TO 1000
{
main.fc.ReaderEntry(number);

//read file

Read("Task1out.txt");

main.fc.ReaderExit(number);
}
} catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}

}



}

这是读者类。

 import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class main{

public static FileControl fc = new FileControl();

final static Lock lock = new ReentrantLock();

public static int readIndex;

public static void incrementIndex(int increment) {


readIndex = readIndex + increment;

}

public static int getIndex()
{
return readIndex;
}



public static void main(String[] args) throws InterruptedException {



Writer [] writer = new Writer[10];
Reader [] reader = new Reader[10];

for(int i = 0; i < 10; i++)
{
reader[i] = new Reader(i);
writer[i] = new Writer(i);
//creating readers and writers

}

for(int i = 0; i < 10; i++)
{
//anonymous threads
//(new Thread(new Writer())).start();
//(new Thread(new Reader())).start();

reader[i].start();
writer[i].start();

}




for(int i = 0; i < 10; i++)
{
try{
reader[i].join();
writer[i].join();
} catch(InterruptedException e){
e.printStackTrace();
}


}






}

}

这是主类。

    import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class FileControl {
final Lock lock = new ReentrantLock();
final Condition writers = lock.newCondition();
final Condition readers = lock.newCondition();
int activereaders = 0;
int waitingwriters = 0;
boolean writing = false;

public void WriterEntry(int number)throws InterruptedException{
lock.lock();
try{
if(writing == true || activereaders > 0){
waitingwriters++;
System.out.println("Writer thread " + number + " : waiting to write");
writers.await();
waitingwriters--;
}
System.out.println("Writer thread " + number + " : ready to write");

writing = true;
}
finally{
lock.unlock();
}


}



public void WriterExit(int number)throws InterruptedException{
lock.lock();
try{
System.out.println("Writer thread " + number + " : finished to write");

System.out.println("writers " + waitingwriters + "readers " + activereaders); //test

if(waitingwriters > 0)
writers.signal();
else{
writing = false;
readers.signal();
}
}
finally{
lock.unlock();
}

}


public void ReaderEntry(int number)throws InterruptedException{
lock.lock();
try{

if(writing == true || waitingwriters > 0){ //remove activereaders > 0
System.out.println("Reader thread " + number + " : waiting to read");
readers.await();
activereaders++;
}


System.out.println("Reader thread " + number + " : ready to read");
}
finally{
lock.unlock();
}

}

public void ReaderExit(int number)throws InterruptedException{
lock.lock();
try{



activereaders--;



System.out.println("Reader thread " + number + " : finished to read");

System.out.println("writers " + waitingwriters + "readers " + activereaders); //test

if(activereaders == 0)
{
if(waitingwriters > 0)
{
writers.signal();
}
else
{
readers.signal();
}
}
}
finally{
lock.unlock();
}

}


}

这是显示器。

pseudocode for the monitor

最佳答案

每当您有多个锁 A、B 和 C 时,如果您不保证代码尝试以相同的顺序获取所述锁,则可能会出现死锁。

final Lock A = new ReentrantLock();
final Lock B = new ReentrantLock();
final Lock C = new ReentrantLock();

A、B、C 或 C、B、A 或 A、C、B - 只要顺序一致即可。

当您尝试使用一个代码路径:A、B、C 时,就会出现问题另一个尝试 C、B、A。

正如你可能猜到的那样,由于 A 和 C 都被持有,两者之一将获得 B,然后两者都会陷入僵局。 (也就是说,资源锁定图中有一个循环)

从形式上讲,只有满足以下所有条件,才会出现死锁:

  1. 无抢占:分配后系统不会释放资源;它们只能通过持有过程来释放。
  2. 循环等待:如上所述。
  3. 互斥:在任何给定时间只有一个进程可以使用资源。
  4. 资源持有:进程当前至少持有一个资源,并正在请求/等待另一个进程持有的其他资源。

最好的解决方案是确保顺序一致或锁定在更高(单一)级别。另一种选择是使用锁定库,该库在尝试锁定时会超时(或使用条件并编写自己的包装器来执行此操作)。但这种方法不适合胆小的人。此方法的某些实现将等待随机时间并重试,但随着锁数量的增加,这可能会非常低效。

资源:

附注我实际上并没有阅读你的太多代码,因为它的格式很差并且不是一个最小的示例(即对于我们的目的来说太冗长了)。但这个建议应该从理论角度回答你的问题。

关于java - 多级锁会导致多线程程序死锁吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19849079/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com