**小白新手写的第一个博客,感觉好难啊,开始有导航的被自己不小心删除了,然后很多都不知道怎么弄,就连代码块都不知道怎么复制粘贴上来,很是难过,如果有大佬知道可以指点迷津一下。**
今天写的是关于Dekker算法和Peterson算法的,因为老师讲到这里,为了以后复习的方便,有机会的话会把博客当作笔记本。
例题:有一个售票系统卖50张票(ticket_cnt),有两个窗口在销售这同一批票(t0、t1),如何设计才不会销售到票数为0呢?(基本约束:“小屋协议”,该协议指的是这个时刻不允许多个线程访问)
这里我们将对最后一张票的使用,称之为“临界资源”,(<Critical section>);为了解决对临界资源的使用,我们引入一个基本思路:“标记”。
Dekker算法
package Test;
public class Test{
public static int turn=1;
public static boolean[] flag = {false,false};
public static void main(String [] args){
Thread t0 = new Thread0();
Thread t1 = new Thread1();
t0.start();
t1.start();
}
}
class Thread0 extends Thread{
public void run(){
Test.turn=1; //将进入小屋的机会推给对方
Test.flag[0]=true;//表明自己想进入小屋
while(flag[1]==true){ //查看对方是否在小屋里面
Test.flag[0]=false; // 对方在小屋,表明自己暂时不想进
while(Test.turn==1){ // 在两方都以为对方在小屋的时候,才起作用。将进小屋机会给对方。
}
Test.flag[0]=true; // 表明自己想进小屋
}
while(true){ // 进小屋
if(Test.ticeket_cnt>0){//查看余票是否大于零
System.out.println(Thread.currentThread().getName()+"销售了NO:"+Test.ticket_cnt--+"张票"); // 输出哪个窗口卖的票及其卖的票的票数名
}else{ //没有余票了
System.out.println(“票卖完了”); //打印“票卖完了”
break; //如果没有该跳转语句将会一直输出“票卖完了“。
}
Test.flag[0]=false; //进入小屋后,出小屋,短暂时间不想进小屋
Test.trun=1;//将进小屋的权利推给对方
}
}
}
class Thread1 extends Thread{ //同上代码块一模一样。
public void run(){
Test.turn=0;
Test.flag[1]=true;
while(Test.flag[0]==true){
Test.flag[1]=false;
while(Test.turn==0){
}
Test.flag[1]=true;
}
while(true){
if(Test.ticeket>0){
System.out.println(Thread.currentThread().getName()+"销售了NO:"+Test.ticket_cnt--+"张票");
}else{
System.out.println(“票卖完了”);
break;
}
Test.flag[1]=false;
Test.trun=0;
}
}
}
下面是Peterson算法,本身含义适合Dekker算法一样,但是其简化了代码量,这并不是一个很简单的事,说明其人是很厉害哒
//将Dekker算法中的Thread0中条件改为
while(flag[1]==true&&turn=1){
//do nothing
}
<caitical section>
flag[0]=false;
//Thread1中的将1改为0,将0 改为1。
总结:该算法是从软件的方面来解决同步和互斥的两进程问题,其缺点是:
①编程解决方法比较难
②很大的不足就是原本只需要写一块的代码的,现在需要写两块。自己可以试着在该代码的基础上修改至三进程。
③纯软件的方法解决不了没有执行的就自动阻塞。大部分cpu时间被阻塞浪费
④思考:又没有这么一种机制:容易扩展多个进程,在没有进入的时候自行阻塞,没有被阻塞的时候又被自动唤醒。
⑤预习信号量。