Main.java:

public class Main {
    public static void main(String[] args) {
        final Semaphore semp = new Semaphore(1);
        for (int facultyNO = 1; facultyNO <= 10; facultyNO++) {
            final int NO = facultyNO;
            Runnable run = new Runnable() {
                public void run() {
                    try {
                        while (true) {
                            semp.acquire();
                            System.out.println("No." + NO + " grab a candy");
                            Bowl.candy--;
                            System.out.println("Candy num left:" + Bowl.candy);
                            semp.release();
                            Thread.sleep((long) (1000));
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            Thread faculty = new Thread(run);
            faculty.setPriority(Thread.MIN_PRIORITY);
            faculty.start();
        }
        Thread TA = new Thread(() -> {
            try {
                while (true) {
                    if (Bowl.candy < 0) {
                        semp.acquire();
                        System.out.println("TA fills the candy bowl");
                        Bowl.candy = 10;
                        System.out.println("Candy num left:" + Bowl.candy);
                        semp.release();
                    }
                }
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        TA.setPriority(Thread.MAX_PRIORITY);
        TA.start();
    }
}


Bowl.java:

public class Bowl {
    static int candy = 10;
}


我将线程“ TA”赋予最高优先级,因为我希望在Bowl.candy = 0填充碗后立即执行该线程。但是,控制台将打印:

No.2 grab a candy
Candy num left:9
No.1 grab a candy
Candy num left:8
No.4 grab a candy
Candy num left:7
No.6 grab a candy
Candy num left:6
No.7 grab a candy
Candy num left:5
No.8 grab a candy
Candy num left:4
No.3 grab a candy
Candy num left:3
No.5 grab a candy
Candy num left:2
No.10 grab a candy
Candy num left:1
No.9 grab a candy
Candy num left:0
No.2 grab a candy
Candy num left:-1
No.1 grab a candy
Candy num left:-2
No.4 grab a candy
Candy num left:-3
No.6 grab a candy
Candy num left:-4
No.7 grab a candy
Candy num left:-5
No.8 grab a candy
Candy num left:-6
No.3 grab a candy
Candy num left:-7
No.5 grab a candy
Candy num left:-8
No.10 grab a candy
Candy num left:-9
No.9 grab a candy
Candy num left:-10


看来if (Bowl.candy < 0)中的代码永远不会执行。为什么?

最佳答案

在这种情况下,您必须先获取锁,然后才能访问变量:

semp.acquire();
if (Bowl.candy < 0) {
    System.out.println("TA fills the candy bowl");
    Bowl.candy = 10;
    System.out.println("Candy num left:" + Bowl.candy);
}
semp.release();


另一个选择:

Bowl.candy必须声明为volatile,否则不能保证其他线程可以看到对此变量的更改。或仅在Bowl.candy块中访问synchronized

10-04 23:31