一个线程访问共享的,可修改的数据时,我们就说它进入了一个临界区(critical section 或 criticl region).
二,互斥问题
1,第一个版本的互斥Dekker算法(Lookstep同步和Busy Waiting)
startThreads();
线程T1:
void main()
{
while (!done)
{
while (threadNumber == 2) ; //线程反复测试threadNumber值,我就说它处于Busy waiting,暂用处理器时间来做无用工作
//critical section code threadNumber = 2;
}
}
线程T2:
void main()
{
while (!done)
{
while (threadNumber == 2) ;
//critical section code threadNumber = 2;
}
}
1),同时启动这2个线程,除非变量threadNumber等于线程号,否则将while循环下去,效率低下。
2),违反互斥原则,不在临界区的线程不应该影响其他希望进入临界区的线程。而这里必须等到T1进入设置threadNumber=2后,T2才可进入。
线程T1:
void main()
{
while (!done)
{
while (t2Inside) ; (1) t2Inside = false
t1Inside = true; (2)此处在执行前,被T2抢占时
//critical section code (4)进入临界区 1
t1Inside = false;
}
线程T2:
void main()
{
while (!done)
{
while (t1Inside) ; (3)t1Inside = false;
t2Inside = true; (4)进入临界区 2
//critical section code
t1Inside = false;f
}
}
2个线程同时都进入了临界区,违反互斥原则。
线程T1:
void main()
{
while (!done)
{
t1WantsToEnter = true;
while (t2WantsToEnter) ; //T2想进入临界区,则t1等待
//critical section code
t1WantsToEnter = false;
}
}
线程T2:
void main()
{
while (!done)
{
t2WantsToEnter = true;
while (t1WantsToEnter) ; //T1想进入临界区,则t2等待
//critical section code
t2WantsToEnter = false;
}
}
假设每个线程同时都发现另一个线程标志为true(即都想进入),那么while就会永远下去,形成死锁。
线程T1:
void main()
{
while (!done)
{
t1WantsToEnter = true;
while (t2WantsToEnter)
{
t1WantsToEnter = false;
//waiting for small, randow amount of time
t1WantsToEnter = true;
}
//critical section code
t1WantsToEnter = false;
}
}
线程T2:
void main()
{
while (!done)
{
t2WantsToEnter = true;
while (t1WantsToEnter)
{
t2WantsToEnter = false;
//waiting for small, randow amount of time
t2WantsToEnter = true;
}
//critical section code
t2WantsToEnter = false;
}
}
我们不能预测异步发生并发的速度,因此与形成死锁类似,也是可能形成无限延期问题,虽然可能性很低,但对于需要严格用途的地方造成伤害。
线程T1:
void main()
{
while (!done)
{
t1WantsToEnter = true;
while (t2WantsToEnter) //(1)当T2想进入且T1是优先线程,则T1跳过if判断,等待T2将t2WantsToEnter设置为false。
{ //(1)当T2想进入且T2是优先线程,则T1进入if判断
if(favoredThread == 2)
{
t1WantsToEnter = false;
while(favoredThread == 2); //(2)测试T2是否任然保持是优先线程
t1WantsToEnter = true; //(3)当T2执行完毕退出时,将t2WantsToEnter=false,favoredThread =1,则T1回到(1)开始进入自己
临界区。如果T2退出时,又抢占将自己设置为true,可优先线程已经是1,将等到T1执行。
}
}
//critical section code
favoredThread = 2;
t1WantsToEnter = false;
}
}
线程T2:
void main()
{
while (!done)
{
t2WantsToEnter = true;
while (t1WantsToEnter)
{
if(favoredThread == 1)
{
t2WantsToEnter = false;
while(favoredThread == 1);
t2WantsToEnter = true;
}
}
//critical section code
favoredThread = 1;
t2WantsToEnter = false;
}
}
线程T1:
void main()
{
while (!done)
{
t1WantsToEnter = true;
favoredThread = 2;
while (t2WantsToEnter && favoredThread == 2) ;
//critical section code
t1WantsToEnter = false;
}
}
线程T2:
void main()
{
while (!done)
{
t2WantsToEnter = true;
favoredThread = 1;
while (t1WantsToEnter && favoredThread == 1) ;
//critical section code
t2WantsToEnter = false;
}
}
boolean choosing[n] //记录哪些线程是否取票
int ticketp[n]; //票据
线程Tx
void main()
{
x = ThreadNumber(); //保存当前线程号;
while(!done)
{
chooseing[x] = true; //开始取票
ticket[x] = maxValue(ticket) + 1;
chooseing[x] = false; //取票完毕
for(int i = 0; i < n; i++) //根据比较票据,来叫号
{
if(i == x) //如果是当前自己,就不需要检查
{
continue;
}
while( chooseing[i] != false ); //在进入临界区之前,其他线程如果没有选好号,则等待。
while( ticket[i] != 0 && ticket[i] < ticket[x] ); //如果当前线程的票号不是最小的,则等待
if(ticket[i] == ticket[x] && i < x)
{
while( ticket[i] != 0); //等待离开临界区
}
}
//critical section code
ticket[x] = 0;
}
}

浙公网安备 33010602011771号