我有一个包含作家和读者的程序,他们的访问权限由监视器控制。
所以,这本应该饿死的,但我陷入了僵局。我想知道为什么,然后我记得我放了另一个锁,我认为在阅读器内部的 read 方法中没有必要这样做,以保护我的全局变量免受不一致的影响。我认为它不会导致任何死锁,因为我可以运行线程 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();
}
}
}
这是监视器。