java - 使用两个线程按顺序使用自定义锁定打印编号,其中一个线程打印偶数,另一个线程打印奇数

标签 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();
            }
        }
    }

最佳答案

您需要使printOdd volatile ,例如

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

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

关于java - 使用两个线程按顺序使用自定义锁定打印编号,其中一个线程打印偶数,另一个线程打印奇数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42772900/

相关文章:

java - 在解析期间访问 JSON 数据中的键时,For 循环未完成

java - 创建标题页 Activity

java - 在运行时交换正在运行的 jar

operating-system - 测试和设置 vs 彼得森算法

java - 尝试使用JButton

java - spring data mongodb - 日期聚合

.net - SQL Server 2008 中 CLR 中的线程

java - JAVA通过并发在静态方法中实现唯一ID号

java - 使用 Java 队列锁

java - 列表迭代 - 通用逻辑