静态方法跟普通的synchronized方法有所区别,需要特别注意的是,虽然静态的同步方法仅允许同时只有一个线程参与访问,但与此同时其他线程依然可以访问另一个由synchronized修饰的非静态方法。在这里,虽然两个线程都是访问同一个对象实例上的方法(其中一个是静态方法,而另一个不是),但是这两个方法却绑定了不同的对象。因此当通过这两个方法修改同一份共享数据时,可能会带来数据一致性的错误。造成该错误的原因是,当程序由synchronized修饰的静态方法调用时,此时方法所关联的对象是类对象而并非该类的实例对象

金额类

package parkingsystem;

public class ParkingCash {
    private static final int cost = 2;

    private long cash;

    public ParkingCash() {
        cash = 0;
    }

    public synchronized void vehiclePay() {
        cash += cost;
    }

    public void close() {
        System.out.printf("Closing accounting");
        long totalAmmount;
        synchronized (this) {
            totalAmmount = cash;
            cash = 0;
        }
        System.out.printf("The total amount is : %d",
                totalAmmount);
    }
}

状态类

package parkingsystem;

public class ParkingStats {
    private final Object controlCars, controlMotorcycles;
    private long numberCars;
    private long numberMotorcycles;
    private ParkingCash cash;

    public ParkingStats(ParkingCash cash) {
        numberCars = 0;
        numberMotorcycles = 0;
        controlCars = new Object();
        controlMotorcycles = new Object();
        this.cash = cash;
    }

    public void carComeIn() {
        synchronized (controlCars) {
            numberCars++;
        }
    }

    public void carGoOut() {
        synchronized (controlCars) {
            numberCars--;
        }
        cash.vehiclePay();
    }

    public void motoComeIn() {
        synchronized (controlMotorcycles) {
            numberMotorcycles++;
        }
    }

    public void motoGoOut() {
        synchronized (controlMotorcycles) {
            numberMotorcycles--;
        }
        cash.vehiclePay();
    }

    public long getNumberCars() {
        return numberCars;
    }

    public long getNumberMotorcycles() {
        return numberMotorcycles;
    }
}

模拟停车行为类

package parkingsystem;

import java.util.concurrent.TimeUnit;

public class Sensor implements Runnable {
    private ParkingStats stats;

    public Sensor(ParkingStats stats) {
        this.stats = stats;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            stats.carComeIn();
            stats.carComeIn();
            try {
                TimeUnit.MILLISECONDS.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            stats.motoComeIn();
            try {
                TimeUnit.MILLISECONDS.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            stats.motoGoOut();
            stats.carGoOut();
            stats.carGoOut();
        }
    }
}

测试类Main

package parkingsystem;

public class Main {
    public static void main(String[] args) {
        ParkingCash cash = new ParkingCash();
        ParkingStats stats = new ParkingStats(cash);

        System.out.printf("Parking Simulator\n");
        int numberSensors = 2 * Runtime.getRuntime().availableProcessors();
        Thread threads[] = new Thread[numberSensors];
        for (int i = 0; i < numberSensors; i++) {
            Sensor sensor = new Sensor(stats);
            Thread thread = new Thread(sensor);
            thread.start();
            threads[i] = thread;
        }

        for (int i = 0; i < numberSensors; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.printf("Number of cars: %d\n",
                stats.getNumberCars());
        System.out.printf("Number of motorcycles: %d\n",
                stats.getNumberMotorcycles());
        cash.close();
    }
}
posted on 2024-10-27 14:12  神圣兽国窝窝乡独行侠  阅读(6)  评论(0编辑  收藏  举报  来源