静态方法跟普通的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
Sensor sensor = new Sensor(stats)
Thread thread = new Thread(sensor)
thread.start()
threads[i] = thread
}
for (int i = 0
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()
}
}