使用两个线程按顺序使用自定义锁定打印编号,其中一个打印甚至是其他打印奇数

时间:2017-03-13 20:32:32

标签: java multithreading locking synchronized

有两个线程,一个是打印偶数,另一个打印奇数。在下面的自定义锁的帮助下,我想按顺序打印数字。问题是打印一些数字后(显示的数字是正确的顺序。)线程正在陷入僵局。我花了一个多小时仍然无法找到问题,对我来说一切似乎都很好。

public class Main{
       public static void main(String[] args){
           Lock lock=new Lock();
           SharedData sharedData=new SharedData(lock);

           Thread th1=new Thread(new EvenWriter(sharedData));
           Thread th2=new Thread(new OddWriter(sharedData));

           th1.start();
           th2.start();
       } 
    }
    class SharedData{
        Lock lock;
        boolean printOdd;
        SharedData(Lock lock){
           this.lock=lock;
           this.printOdd=true;
        }
    }
    class OddWriter implements Runnable{
        SharedData sharedData;
        int num;
        Lock lock;
        public OddWriter(SharedData sharedData){
           this.sharedData=sharedData;
           this.num=1;
           this.lock=sharedData.lock;
        }
        public void run(){
           while(true){
             if(sharedData.printOdd){
               lock.lock();
               System.out.println(num);
               num=num+2;
               sharedData.printOdd=false;
               lock.unlock();
            }
           }
        }
    }
    class EvenWriter implements Runnable{
        SharedData sharedData;
        int num;
        Lock lock;
        public EvenWriter(SharedData sharedData){
           this.sharedData=sharedData;
           this.num=2;
           this.lock=sharedData.lock;
        }
        public void run(){
           while(true){
             if(!sharedData.printOdd){
               lock.lock();
               System.out.println(num);
               num=num+2;
               sharedData.printOdd=true;
               lock.unlock();
            }
           }
        }
    }
    class Lock{

        private boolean locked=false;
        public synchronized void lock(){

            while(locked){
               try{
                 wait();
               }
               catch(Exception e){
                   e.printStackTrace();
               }
            }

            locked=true;
        }
        public synchronized void unlock(){
            locked=false;
            try{
              notifyAll();
            }
            catch(Exception e){
               e.printStackTrace();
            }
        }
    }

2 个答案:

答案 0 :(得分:0)

您需要制作printOdd volatile,例如

class SharedData{
    Lock lock;
    volatile boolean printOdd;
    SharedData(Lock lock) {
       this.lock=lock;
       this.printOdd=true;
    }
}

这是因为您在多个线程中使用printOdd; volatile的目的是确保所有线程都可以访问一块内存。您之前所做的是允许printOdd仅访问OddWriter线程,因为它是第一个访问它的线程。

答案 1 :(得分:-1)

两个线程之间共享的数据是原子的。在您的情况下,boolean printOdd在线程之间共享,这是导致死锁的原因。 你能用吗

AtomicBoolean printOdd;