我在这里要做的是按偶数消费者打印偶数,按奇数消费者打印奇数。

evenodd方法基本上消耗了任何数字并打印(无论是偶数还是奇数)。我有2个even使用者线程,2个odd使用者线程,2个evenodd使用者线程和3个producer线程。

我对信号量概念不熟悉,因此尝试使用它。当我删除evenodd方法和相关线程时,我得到正确的输出,即偶数由偶数线程组成,奇数由奇数线程组成。但是,当我再次放置evenodd方法和evenodd线程时,出现死锁。

如果有人可以在这方面指导我,我哪里出了问题以及如何解决它,这将非常有帮助。请说明我如何实现evenodd方法,以便它可以正常工作。

package lab61;

import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.Semaphore;

public class Process {

    Semaphore empty;
    Semaphore full;
    Semaphore even;
    Semaphore odd;
    Semaphore mutex;
    //Semaphore evenodd;
    boolean evenb;
    boolean oddb,eo;

    LinkedList<Integer> list;
    Random random;


    public Process(int capacity){
            list=new LinkedList<Integer>();

            empty=new Semaphore(capacity);

            full=new Semaphore(0,true);
            mutex=new Semaphore(1,true);

            even=new Semaphore(0,true);
            evenb=false;
            oddb=false;
            eo=false;

            odd=new Semaphore(0,true);
            //evenodd = new Semaphore(0,true);

            random=new Random();
    }

    public void Producer() throws InterruptedException{

        while(true){

        int a=random.nextInt(100);

        empty.acquire();
        mutex.acquire();

            list.add(a);
            System.out.println("Producing "+a);
            System.out.println(list);



            if((list.get(0)%2)==0){
                if(!evenb){
                 even.release();
                evenb = true;
                }
            }else if((list.get(0)%2)==1){
                if(!oddb){
                 odd.release();
                oddb = true;
                }


            }
            /*if(((list.get(0)%2)==0)||((list.get(0)%2)==1)){
                if(!eo){
                    evenodd.release();
                    eo = true;
                }
            }*/


        mutex.release();


        full.release();


        }

    }

  public void consumereven() throws InterruptedException{
      while(true){
      //Thread.sleep(2000);
          even.acquire();
          Thread.sleep(2000);
          full.acquire();

          mutex.acquire();

            int value = list.removeFirst();
            System.out.println("I am the even consumer "+ value);
            evenb = false;
            System.out.println(list);

          mutex.release();
          empty.release();

      }

  }


  public void consumerodd() throws InterruptedException{
      while(true){

          //Thread.sleep(2000);
          odd.acquire();
          Thread.sleep(2000);
          full.acquire();
          //odd.acquire();
          mutex.acquire();
            int value = list.removeFirst();
            System.out.println("I am the odd consumer "+ value);
            System.out.println(list);
          oddb = false;
          mutex.release();
          empty.release();

      }

  }
 public void evenodd() throws InterruptedException {
      while(true){

          full.acquire();
          mutex.acquire();
          int value = list.removeFirst();
          System.out.println("i am the evenodd consumer " + value );

          if((list.get(0)%2)==0){
              if(oddb=true){
                  odd.acquire();
                  oddb=false;
              }
              if(evenb==false){
                  even.release();
                  evenb = true;
              }
          }
          else if((list.get(0)%2)==1){
              if(evenb=true){
                  even.acquire();
                  evenb=false;
              }
              if(oddb==false){
                  odd.release();
                  oddb = true;
              }
          }
          System.out.println(list);


          mutex.release();
          empty.release();
      }
  }



    }
package lab61;

import lab6.producer;

public class App {


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

        Process p=new Process(10);


        Thread producer1=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    p.Producer();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        });


        Thread producer2=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    p.Producer();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        });

        Thread producer3=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    p.Producer();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        });



        Thread consumereven1=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    p.consumereven();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



            }
        });

Thread consumereven2=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    p.consumereven();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



            }
        });

Thread consumerodd1=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    p.consumerodd();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



            }
        });
Thread consumerodd2=new Thread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            p.consumerodd();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }
});
Thread evenodd1=new Thread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            p.evenodd();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }
});
Thread evenodd2=new Thread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            p.evenodd();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }
});


        producer1.start();
        producer2.start();
        producer3.start();
        consumereven1.start();
        consumereven2.start();
        consumerodd1.start();
        consumerodd2.start();
        evenodd1.start();
        evenodd2.start();

        producer1.join();
        producer2.join();
        producer3.join();
        consumereven1.join();
        consumereven2.join();
        consumerodd1.join();
        consumerodd2.join();
        evenodd1.join();
        evenodd2.join();

    }





}

最佳答案

该代码可能导致死锁,因为consumereven()consumerodd()方法在evenodd信号量之前获取fullmutex信号量,而evenodd()方法获取full和在mutexeven信号灯之前的信号灯。这导致这样的情况,例如,运行odd的线程具有consumereven()信号量,但是在等待even信号量时被阻塞,而运行evenodd()的线程具有full信号量,但是被阻塞在full信号量上,因此两个线程处于死锁状态。

为防止死锁,当您使用多个锁时,最好始终以相同的顺序获取它们,无论它们在何处使用,并以相反的获取顺序释放它们。

10-06 05:14