我正在尝试用Java实现Peterson's algorithm,并且目前已经创建了以下内容

public class Peterson {
    private volatile boolean[] flag = new boolean[2];
    private volatile int victim;

    public void lock(int id)
    {
        //System.out.println(id);
        int i = id;
        int j = 1 - id;
        flag[i] = true;
        victim = i;
        while (flag[j] && victim == i) {};
    }

    public void unlock(int id)
    {
        flag[id] = false;
    }
}


我得到以下代码来测试锁...

class Counter {
    private int value;

    public Counter(int c)   {
        value = c;
    }

    public int get()
    {
        return value;
    }

    public int getAndIncrement()    {
        return value++;
    }
}


class Thread1 implements Runnable   {
    private Counter c;
    private int id;
    private List<Integer> values;
    private Peterson lock;

    public Thread1(Counter c, int id, List<Integer> values, Peterson l) {
        this.c = c;
        this.id = id;
        this.values = values;
        this.lock = l;
    }

    public void run() {

        while (true)
        {
            lock.lock(id);
            try {
                try {

                    if (c.get() > 20000)
                        return;

                    int n = c.getAndIncrement();
                    values.add(n);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            finally {
                lock.unlock(id);
            }
        }
    }
}

public class Tmp    {

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

        Counter  c = new Counter(1);
        Thread[] t = new Thread[2];
        List<Integer> values = new ArrayList<Integer>();
        Peterson l =  new Peterson();

        for (int i = 0; i < t.length; ++i)  {
            t[i] = new Thread(new Thread1(c, i, values, l));
            t[i].start();
        }

        System.out.println(values.size());
    }
}


尽管我希望System.out.println(values.size());打印20000它在每次运行时都打印不同的数字。为什么是这样?我做错什么了?

最佳答案

解锁以确保发生之前不会创建内存屏障

添加volatile boolean barr并在解锁中对其写入true,并将锁中的时间更改为while (barr && flag[j] && victim == i) {};

这样,您就不必等待创建的线程

for (int i = 0; i < t.length; ++i)  {
    t[i] = new Thread(new Thread1(c, i, values, l));
    t[i].start();
}

for (int i = 0; i < t.length; ++i)  {
    try{
        t[i].join();
    }catch(InterruptedException e){
        Thread.currentThread().interrupt();//don't expect it but good practice to handle anyway
    }
}

09-30 20:37