PostgreSQL数据库锁机制——自旋锁浅析( 四 )


大明继续说道:“另外,我们也应该处理一些特殊的情况,比如尝试了很多次TAS之后仍然无法获得锁资源,那么就进入sleep,也就是交出CPU资源,需要注意的是睡眠的时间是随机的,但不能超出上下界 。”
//第一次sleep的时间,sleep的时间逐步递增,第一次是1000微秒if (status->cur_delay == 0) /* first time to delay? */status->cur_delay = MIN_DELAY_USEC;pg_usleep(status->cur_delay);
“当然,如果旋转了很长时间,仍然没有办法获得锁资源,就进入自杀模式,因为我们假设自旋锁保护的临界区都很短,如果很长时间还获取不到锁资源,那么就可能出问题了 。”
if (++(status->delays) > NUM_DELAYS)s_lock_stuck(status->file, status->line, status->func);
“这基本上就是自旋锁的实现了,不过还需要注意我们只谈了X86架构下的实现方法,在不同的CPU架构下,TAS的实现是不同的,比如在MIPS架构下提供的是ll和sc指令,我们要借助这两个指令来实现TAS 。”
“明白了,看来我需要学的东西还有很多 。”小明沮丧的说 。
“不要这么悲观嘛,你不了解这些知识主要是因为你还没有参加工作,还是学生,还在学习的阶段,等你参加工作了,时间长了,也就习惯了 。”大明笑着说,“反正债多了不愁,在我们结束之前,再来补充一下自旋锁释放的知识 。
“锁的释放,直接把值设置成0就可以了嘛 。”
“bingo!是的,我也是这么认为的,但是还有一个注意事项 。”
“什么注意事项,难道这还有什么幺蛾子吗?”小明惊奇道 。
“有一个很大的幺蛾子,就是目前很多CPU为了提高执行效率,实现了乱序执行功能,关于乱序执行的具体内容我们就不展开了,以免你不好消化 。不过需要记住的是,如果把释放锁写成只是简单设置lock的值,由于乱序执行的作用,有些临界区中的指令可能会在lock释放后才执行,这就相当于两个进(线)程共同进入了临界区,那肯定会出问题,所以我们可以采用内存屏障的方式来保证锁释放的有序性,你看,的有些锁释放时用的是这种方式 。”说着,大明在源代码中标出了一行锁释放的代码:do { (); *(lock) = 0; } while (0) 。
“好吧,我记下了,念了这么多年的书,我觉得还是幼儿园适合我 。”小明苦着脸说 。