内部锁Synchronized与重入锁ReentrantLock,一次都只允许一个线程访问一个资源,而信号量却可以指定多个线程,同时访问一个资源及其副本。
用代码模拟停车场:
/*
* 车位信息
*/
publicclassSpace {
privateintid;//车位编号
privatebooleanused=false;//是否已占用;
publicSpace(intid,booleanused){
this.id=id;
this.used=used;
}
publicsynchronizedbooleanisUsed() {
returnused;
}
publicsynchronizedvoidsetUsed(booleanused) {
this.used=used;
}
publicintgetId() {
returnid;
}
}
/*
* 停车
*/
publicclassParkextendsSpaceimplementsRunnable {
privateSemaphoresemaphore=null;
publicPark(intid,booleanused,Semaphoresemaphore) {
super(id,used);
this.semaphore=semaphore;
}
@Override
publicsynchronizedvoidrun() {
try{
this.setUsed(true);
System.out.println("当前车位被占用"+this.getId()+"毫秒,id="+this.getId()+";车位状态,used="+this.isUsed());
Thread.sleep(this.getId());
this.setUsed(false);
this.semaphore.release();
}catch(Exceptione) {
e.printStackTrace();
}
}
}
/*
* 停车场
*/
publicclassParkingLot {
privatePark[]parks=null;
/*
* count个空闲的车位
*/
publicParkingLot(intcount,Semaphoresemaphore){
this.parks=newPark[count];
for(inti=0;i
parks[i]=newPark(i+1,false,semaphore);
}
}
/*
* 返回空闲的车位
*/
publicList getFreeSpace(intcount){
ArrayListal=newArrayList();
intjs=0;
for(inti=0;i
if(parks[i].isUsed()==false){//空闲的
al.add(parks[i]);
js++;
if(js>=count){
break;
}
}
}
returnal;
}
/*
* 把车停到某个车位
*/
publicvoidparking(Parkpark){
try{
if(park.isUsed()==false){//空闲的
Threadth=newThread(park);
th.start();//开始占用这个车位;
}else{
System.out.println("没有找到空闲的车位");
}
}catch(Exceptione){
e.printStackTrace();
}
}
publicstaticvoidmain(String[]args)throwsInterruptedException{
Semaphoresemaphore=newSemaphore(5);//5个信号量,相当于允许5个线程同时访问共享资源;
ParkingLotparkingLot=newParkingLot(5,semaphore);//停车场有5个车位
intpc=0;//批次
while(pc<20){
Randomrd=newRandom();
intcount=rd.nextInt(5);//场外有了count辆车
Listal=parkingLot.getFreeSpace(count);
semaphore.acquire(al.size());
pc++;
System.out.println("可以安排"+al.size()+"辆车进入停车场,这是第"+pc+"批");
intfact=al.size();//实际进场的车辆数
for(inti=0;i
parkingLot.parking(al.get(i));
}
}
}
}