一个线程面试题中代码遇到的问题

Pack 发布于 2020-02-13 21:30
阅读 272
收藏 0
分类:面试与就业

三个人跑步,依次翻越障碍,必须3个人都翻阅一个时候,大家才能翻阅下一个。
我代码基本实现,但是有个问题。

import java.util.Random;

public class ThreadNumber {
//存有三个人跑的距离
public static class Num {
int m = 1;
int j = 1;
int g = 1;

}

/**
 * 线程交替标识,true跑完了
 */


/**
 * 打印奇数的线程类
 */
public static class Mming implements Runnable {
    Num num;
//此段是否跑完
    boolean flagM = false;

    public Mming(Num num) {
        this.num = num;
    }

    @Override
    public void run() {
        while (num.m <= 3) {
            if ((!flagM)) {
                System.out.println("m开始跑" + num.m + "个" + current());

                int time = randomNum();
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Mming花了" + time + "跑完第" + num.m + "个" + current());
                num.m++;
                flagM = true;

//检查另外两人是否跑完
if (num.j >= num.m && num.g >= num.m) {
flagM = false;
}

            } else {
                if (num.j >= num.m && num.g >= num.m) {
                    flagM = false;
                }
                System.out.println("!!!!!!!");
            }
        }

    }
}

/**
 * 打印偶数的线程类
 */
public static class Jordan implements Runnable {
    Num num;
    boolean flagJ = false;

    public Jordan(Num num) {
        this.num = num;
    }

    @Override
    public void run() {
        while (num.j <= 3) {

            if ((!flagJ)) {
                System.out.println("j开始跑" + num.j + "个" + current());

                int time = randomNum();
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Jordan花了" + time + "跑完第" + num.j + "个" + current());
                num.j++;
                flagJ = true;
                if (num.m >= num.j && num.g >= num.j) {
                    flagJ = false;
                }

            } else {
                if (num.m >= num.j && num.g >= num.j) {
                    flagJ = false;
                }
                System.out.println("!!!!!!!");
            }

        }
    }
}

public static class Guai implements Runnable {
    Num num;
    boolean flagG = false;

    public Guai(Num num) {
        this.num = num;
    }
    @Override
    public void run() {
        while (num.g <= 3) {
            if ((!flagG)) {
                System.out.println("g开始跑" + num.g + "个" + current());
                int time = randomNum();
                try {
                    Thread.sleep(time);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Guai花了" + time + "跑完第" + num.g + "个" + current());
                num.g++;
                flagG = true;
                if (num.m >= num.g && num.j >= num.g) {
                    flagG = false;
                }
            } else {
                if (num.m >= num.g && num.j >= num.g) {
                    flagG = false;
                }
                System.out.println("!!!!!!!");
            }
        }

    }
}

volatile static Num num = new Num();

public static void main(String[] args) {
    new Thread(new Guai(num)).start();
    new Thread(new Mming(num)).start();
    new Thread(new Jordan(num)).start();
    
}

public static int randomNum() {
    Random rand = new Random();

    return rand.nextInt(1000) + 1000;
}


public static String current() {

    return Long.toString(System.currentTimeMillis());

}

}

这段代码执行可以,但是如果把 System.out.println("!!!!!!!");删除。执行就会卡死。完全搞不明白为什么!!!!!!!求助

359
Pack
Pack

这个应该是可见性的问题,尝试在Num类的三个变量上加上volatile,你在外围的对象num上加了volatile,作用是num引用发生变化了,才会同步主内存,线程工作内存失效,你改变里面的值并不会发生上面的操作;为什么用了System.out.println("!!!!!!!");这个也可以呢?这是因为System.out.println()这个方法底层用到了synchronized关键字

请先 登录 后评论