靜態方法跟普通的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()
}
}