Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在writer-reader中使用信号量_Java_Multithreading_Semaphore - Fatal编程技术网

Java 在writer-reader中使用信号量

Java 在writer-reader中使用信号量,java,multithreading,semaphore,Java,Multithreading,Semaphore,所以我正在参加一门多线程开发课程,目前正在学习信号量。在我们最近的任务中,我们应该使用三个线程和两个队列。writer线程将字符写入第一个队列,然后“encryptor”线程将从该队列读取字符,加密字符,然后将其添加到第二个队列。然后我们有一个从第二个队列读取的读线程。为了处理同步,我们应该使用信号量和互斥,但我没有使用任何: public class Buffer { private Queue<Character> qPlain = new LinkedList<Chara

所以我正在参加一门多线程开发课程,目前正在学习信号量。在我们最近的任务中,我们应该使用三个线程和两个队列。writer线程将字符写入第一个队列,然后“encryptor”线程将从该队列读取字符,加密字符,然后将其添加到第二个队列。然后我们有一个从第二个队列读取的读线程。为了处理同步,我们应该使用信号量和互斥,但我没有使用任何:

public class Buffer {
private Queue<Character> qPlain = new LinkedList<Character>();
private Queue<Character> qEncrypt = new LinkedList<Character>();
private final int CAPACITY = 3;

public Buffer() {
    System.out.println("New Buffer!");
}

public synchronized void addPlain(char c) {
    while (qPlain.size() == CAPACITY) {
        try {
            wait();
            System.out.println("addPlain is waiting to add Data");
        } catch (InterruptedException e) {
        }
    }
    qPlain.add(c);
    notifyAll();
    System.out.println("addPlain Adding Data-" + c);
}

public synchronized char removePlain() {
    while (qPlain.size() == 0) {
        try {
            wait();
            System.out.println("----------removePlain is waiting to return Data.");
        } catch (InterruptedException e) {
        }
    }
    notifyAll();
    char c = qPlain.remove();
    System.out.println("---------------removePlain Returning Data-" + c);
    return c;
}

public synchronized void addEncrypt(char c) {
    while (qEncrypt.size() == CAPACITY) {
        try {
            wait();
            System.out.println("addEncrypt is waiting to add Data");
        } catch (InterruptedException e) {
        }
    }

    qEncrypt.add(c);
    notifyAll();
    System.out.println("addEncrypt Adding Data-" + c);
}

public synchronized char removeEncrypt() {
    while (qEncrypt.size() == 0) {
        try {
            wait();
            System.out.println("----------------removeEncrypt is waiting to return Data.");
        } catch (InterruptedException e) {
        }
    }
    notifyAll();
    char c = qEncrypt.remove();
    System.out.println("--------------removeEncrypt Returning Data-" + c);
    return c;
}

}
公共类缓冲区{
private Queue qPlain=new LinkedList();
私有队列qEncrypt=new LinkedList();
私人最终国际通行能力=3;
公共缓冲区(){
System.out.println(“新缓冲区!”);
}
公共同步void addPlain(字符c){
while(qPlain.size()=容量){
试一试{
等待();
System.out.println(“addPlain正在等待添加数据”);
}捕捉(中断异常e){
}
}
qPlain.add(c);
notifyAll();
System.out.println(“添加数据的addPlain-”+c);
}
公共同步的char removePlain(){
而(qPlain.size()=0){
试一试{
等待();
System.out.println(“------------removePlain正在等待返回数据”);
}捕捉(中断异常e){
}
}
notifyAll();
char c=qPlain.remove();
System.out.println(“--------------removePlain返回数据-”+c);
返回c;
}
公共同步作废补遗(字符c){
while(qEncrypt.size()=容量){
试一试{
等待();
System.out.println(“addEncrypt正在等待添加数据”);
}捕捉(中断异常e){
}
}
qEncrypt.添加(c);
notifyAll();
System.out.println(“添加数据的加密-”+c);
}
公共同步字符removeEncrypt(){
while(qEncrypt.size()=0){
试一试{
等待();
System.out.println(“------------removeEncrypt正在等待返回数据。”);
}捕捉(中断异常e){
}
}
notifyAll();
char c=qEncrypt.remove();
System.out.println(“--------------removeEncrypt返回数据-”+c);
返回c;
}
}
这很好,但我不会通过,因为我没有使用任何信号量。我确实理解这个概念,但我不认为在这种情况下使用任何东西有什么意义。我有两个队列,每个队列只有一个读写器

编辑:改为使用信号量更新。它几乎可以工作,当队列为空时调用removePlain()方法get时,问题就出现了。我很确定我应该阻止它,但我在这里迷路了。我可以不在这里使用互斥吗

public class Buffer {
private Semaphore encryptedSem = new Semaphore(0);
private Semaphore decryptedSem = new Semaphore(0);
private final Queue<Character> qPlain = new LinkedList<Character>();
private final Queue<Character> qEncrypt = new LinkedList<Character>();
private final int CAPACITY = 3;
private boolean startedWrite = false;
private boolean startedRead = false;

/**
 * Adds a character to the queue containing non encrypted chars.
 * 
 * @param c
 */
public void addPlain(char c) {

    // Makes sure that this writer executes first.
    if (!startedWrite) {
        startedWrite = true;
        encryptedSem = new Semaphore(1);
    }

    if (qPlain.size() < CAPACITY) {
        aquireLock(encryptedSem);
        System.out.println("addPlain has lock");
        qPlain.add(c);
        realeseLock(encryptedSem);
    }
}

/**
 * Removes and returns the next char in the non encrypted queue.
 * 
 * @return
 */
public char removePlain() {
    // TODO Need to fix what happens when the queue is 0. Right now it just
    // returns a char that is 0. This needs to be blocked somehow.

    char c = 0;

    if (qPlain.size() > 0) {
        aquireLock(encryptedSem);
        System.out.println("removePlain has lock");
        c = qPlain.remove();
        realeseLock(encryptedSem);
    } else {
        System.out.println("REMOVEPLAIN CALLED WHEN qPlain IS EMPTY");
    }
    return c;
}

/**
 * Adds a character to the queue containing the encrypted chars.
 * 
 * @param c
 */
public void addEncrypt(char c) {
    if (!startedRead) {
        startedRead = true;
        decryptedSem = new Semaphore(1);
    }

    if (qEncrypt.size() < CAPACITY) {
        aquireLock(decryptedSem);
        System.out.println("addEncrypt has lock");
        qEncrypt.add(c);
        realeseLock(decryptedSem);
    }

}

/**
 * Removes and returns the next char in the encrypted queue.
 * 
 * @return
 */
public char removeEncrypt() {
    char c = 0;
    if (qEncrypt.size() > 0) {
        aquireLock(decryptedSem);
        System.out.println("removeEncrypt has lock");
        c = qEncrypt.remove();
        realeseLock(decryptedSem);

    }
    return c;
}

/**
 * Aquries lock on the given semaphore.
 * 
 * @param sem
 */
private void aquireLock(Semaphore sem) {
    try {
        sem.acquire();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

/**
 * Realeses lock on the given semaphore.
 * 
 * @param sem
 */
private void realeseLock(Semaphore sem) {
    sem.release();
}
公共类缓冲区{
私有信号量encryptedSem=新信号量(0);
私有信号量decryptedSem=新信号量(0);
private final Queue qPlain=new LinkedList();
private final Queue qEncrypt=new LinkedList();
私人最终国际通行能力=3;
私有布尔startedWrite=false;
私有布尔startedRead=false;
/**
*向包含未加密字符的队列中添加字符。
* 
*@param c
*/
公共空白地址(字符c){
//确保此写入程序首先执行。
如果(!startedWrite){
startedWrite=true;
encryptedSem=新信号量(1);
}
if(qPlain.size()<容量){
aquireLock(加密扫描电镜);
System.out.println(“addPlain有锁”);
qPlain.添加(c);
realeseLock(encryptedSem);
}
}
/**
*删除并返回非加密队列中的下一个字符。
* 
*@返回
*/
public char removePlain(){
//TODO需要修复队列为0时发生的情况。现在它只是
//返回一个0字符。需要以某种方式阻止该字符。
字符c=0;
如果(qPlain.size()>0){
aquireLock(加密扫描电镜);
System.out.println(“removePlain有锁”);
c=qPlain.remove();
realeseLock(encryptedSem);
}否则{
System.out.println(“当qPlain为空时调用REMOVEPLAIN”);
}
返回c;
}
/**
*向包含加密字符的队列中添加字符。
* 
*@param c
*/
公共作废补遗(字符c){
如果(!startedRead){
startedRead=true;
decryptedSem=新信号量(1);
}
if(qEncrypt.size()<容量){
阿奎雷洛克(解密扫描电镜);
System.out.println(“addEncrypt有锁”);
qEncrypt.添加(c);
realeseLock(decryptedSem);
}
}
/**
*删除并返回加密队列中的下一个字符。
* 
*@返回
*/
公共字符删除加密(){
字符c=0;
如果(qEncrypt.size()>0){
阿奎雷洛克(解密扫描电镜);
System.out.println(“removeEncrypt有锁”);
c=qEncrypt.remove();
realeseLock(decryptedSem);
}
返回c;
}
/**
*aquiries锁定给定的信号量。
* 
*@param-sem
*/
专用void aquireLock(信号量sem){
试一试{
sem.acquire();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
/**
*Realeses锁定给定的信号量。
* 
*@param-sem
*/
私有void realeseLock(信号量sem){
sem.release();
}

}

好的,那么试着解决你的问题,而不做家庭作业:-)

关于你的第一个样品 乍一看,这是一个工作样本。您正在通过
synchronized
关键字使用互斥形式,该关键字允许您正确使用
this.wait/notify
。这还提供了确保每个线程在同一个监视器上同步的保护措施,从而在安全之前提供足够的

换句话说,多亏了这一个监视器,您可以确信
synchronized
方法下的任何内容都是以独占方式执行的,并且这些方法的副作用在其他方法中是可见的

唯一的小问题是,您的队列不是
最终的
,这取决于指导原则和整个系统/线程的引导方式
if (qPlain.size() > 0) {
    aquireLock(encryptedSem);
    ...
    c = qPlain.remove();
    realeseLock(encryptedSem);
} else {
    System.out.println("REMOVEPLAIN CALLED WHEN qPlain IS EMPTY");
}
acuquireSemaphore();
try { 
    // do something
} finally {
    releaseSemaphore();
}