哈哈,好,我接下来做个比较详细清晰明了的解析:
首先来解释一下x锁和s锁的定义:
共享锁【S锁】
又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
排他锁【X锁】
又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
摘自:《yuwei19840916的专栏-csdn》
为什么非要加2把锁呢?加一把不就够了吗?
释疑:我的确很愚蠢地尝试过去加一把排他X_Lock,就象这样:
有一个公有变量V=10,线程A与线程B都会用到,它们都允许读取修改V。
好了,现在只有一把锁Lock,专门用于控制V的修改权,假如某个线程要修改V了,就给V加X-Lock(读就不需要了加了),那么其余线程此时不允许对V加X-Lock,也不允许读V。
这些严格的条件看起来貌似万无一失,V应该会被AB两线程很合理的利用吧,但是噩梦开始了~
假如 x-lock此时为false,只有A线程正在准备读V的值,但不修改,情景就像如下这样。
A线程:
while(X-lock)// X-lock为false
{
wait(10);
}
--------------markA------------
read(V);
正如以上代码所说,A线程正检测V是否被加X-Lock,一旦发现x-lock为false,就进行下一步read(V),呵呵,假如x-lock一直为假(这时期B线程一直不去修改V),那么A线程读到的值当然是正确的了。但是在markA位置,假如A线程时间片到了,并且B线程突然要修改V,给V++,B线程此时加x-lock锁,不过,呵呵A线程已经跳过了检测锁的代码了,B线程如何加锁都不管用了,就像这样:
v=10;
-----A线程-----
while(X-lock)// X-lock为false
{
wait(10);
}
-----B线程-----
x-lock=true;
v++;//v=11;
-----A线程-----
read(v);//read v=11
******exception thrown: A should read v=10,rather than 11******
-----B线程-----
x-lock=false;
故事就是这样了,A线程在不知情的情况下读到了v=11,而事实上,A需要读V=10才符合要求。这就是加一把锁的问题所在了。毕竟因为两个不同的线程,你永远不知道什么时候AB线程在哪个地方切换!就算是v=v+1的一句很普通的话,一个线程都有可能分两次走,因为机器执行的是机械代码,而不是高级语言,v=v+1会变转变为汇编语言,
mov al,A ;A→al
add al,1 ;A+1→al
这样线程很可能在第一句执行完交出执行权给别的线程,别的线程可能在此时改掉A的值,导致悲剧的发生。
嗯,估计大家现在知道发生什么事了吧,加一把锁的问题在于,检测锁的代码有时候不起作用~~
那为什么两把锁就能够解决上面的问题呢?
呵呵,继续看下去,你就知道了~~
现在同样的情况,只是多了一把s-lock,凡是要读v值的线程,先给他加s锁,读完之后在解锁
v=10;
-----A线程-----
while(X-lock)// X-lock此时为false
{
wait(10);
}//保证x-lock为假,才能给s-lock=true;
s-lock=true;//*********注意,A线程在<"想">读V值时,加s锁啦
while(X-lock)// 再次确定x-lock为假,X-lock此时为false
{
wait(10);
}
-----B线程-----
while(s-lock==true)//b线程要加X锁时,必须要保证s锁为假
{
wait(10);
}
//B线程等不到s-lock为假就被迫交出执行权了,接着到A执行
---------A线程--------
read(v);//read v=10
s-lock=false;//A线程读完了,解开s-lock
---------B线程----------
while(s-lock==true)//b线程要加X锁时,必须要保证s锁为假
{
wait(10);
}
x-lock=true;
v++;//v=11;
-----A线程-----
//no mission
-----B线程-----
x-lock=false;
好了,问题貌似真的解决了,其实加两把锁比加一把实际,是因为,两把锁能够锁得更“牢固”些!!肯定比一把锁好嘛。
可能以上例子有bug,请读者认真研读指正(我强烈的感觉,这个例子有问题,请指正问题)。 |