免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1880 | 回复: 7
打印 上一主题 下一主题

pppk之Recipe5.3(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-21 20:18 |只看该作者 |倒序浏览
本帖最后由 zhuyubei 于 2012-08-21 20:19 编辑

今天我们讲Recipe5.3: Hash的锁,分2天完成。在我完成这个Recipe之前,我以前没接触过这方面的内容。所以实践下来,感觉有些收获。hash的锁操作,为多线程下的编程提供了一定的安全机制。也许我下面的Recipe会趁热打铁继续讲锁,只不过是Recipe7.18文件锁。

本Recipe引用语句是
  1. 我这里有《王摩诘全集》,你且把他的五言律读一百首,细心揣摩透熟 了,然后再读一二百首老杜的七言律,次再李青莲的七言绝句读一二百首。肚子 里先有了这三个人作了底子,然后再把陶渊明、应瑒,谢、阮、庾、鲍等人的一 看。你又是一个极聪敏伶俐的人,不用一年的工夫,不愁不是诗翁了! --《红楼梦》林黛玉
复制代码
我们顺便再回顾下我实践的进展
在pppk/目录下,有个文件叫Readme。如果你checkout了,你可以看下我实现的进展
Recipe  P1     P2      RootRecipe
1.1        Perl        Python
1.2         Perl         Python       
1.3        Perl        Python        1.1
1.4
5.1         Perl                5.3
5.2         Perl                5.3
5.3     Perl
5.4         Perl                5.3
5.6         Perl                5.3
7.11         Perl
8.2        Perl
8.4        Perl                       

我们讲了Recipe1.1, Recipe1.2。 但其实我已经完成了一些Recipe。其中有些Recipe会以类似的情况出现在其他的Recipe里,这样我们就不费心去完成这些Recipe.

应该说python这块,我做得比较吃力。有些力不从心。关键是,我期望能用和Perl类似那样的标准库去实现,但是情况不是很理想。当然我Python弱不少。好在毕竟是Perl的板块,Perl这块还是尽力完成了。当然有这个文件做参照,我们一定会把它都完成的。

每完成一个Recipe,就像《圣斗士》里打冥界的时候沙加手里的佛珠串一样,又会有一颗佛珠变黑了。

论坛徽章:
0
2 [报告]
发表于 2012-08-21 20:25 |只看该作者
无论要不要锁住Hash,为了方便我们都需要去展示一个Hash。当然可以用Dumper之类的方法。不过我们参照Recipe5.6,写了个一个函数来完成它:
  1. sub printHash
  2. {
  3.         my ( $rhAHash ) = shift;
  4.         if ( $rhAHash and ( ref($rhAHash) eq "HASH" ) ){
  5.                 print "+++++ Hash Begin\n";
  6.                 print map { "Key: [$_] and Value: [$rhAHash->{ $_ }]\n" } keys %{ $rhAHash };
  7.                 print "+++++ Hash End\n";
  8.         }
  9. }
复制代码
处于效率考虑,我们传了个散列的引用进去,并会做简单的检查。然后我们利用map函数来引发打印的动作
。对于map函数,记得小骆驼的最后几章有介绍。大家可以参考之。当然也许以后的Recipe我也会涉及。我们会利用这个函数来显示一个hash

论坛徽章:
0
3 [报告]
发表于 2012-08-21 20:29 |只看该作者
本帖最后由 zhuyubei 于 2012-08-22 00:04 编辑

为了要对Hash进行锁操作,需要导入模块,并import可能所需要的函数

  1. use Hash::Util qw( lock_keys unlock_keys

  2.                 lock_value unlock_value

  3.                 lock_hash unlock_hash

  4. );
复制代码
其中lock_keys可以锁住当前hash的keys,或所指定的keys,而lock_value可以锁住指定key对应的value。而lock_hash则可以锁住整个Hash的Key/Value

论坛徽章:
0
4 [报告]
发表于 2012-08-21 20:40 |只看该作者
我们先创建一个示例Hash
  1. my %hTestHash = ( "TWO" => 2, "THREE" => 3);
  2. # Recipe 5.1
  3. $hTestHash{ ONE } = 1;
复制代码
下面我们试图锁住这个hash当前的key,再试图删除在锁之前就已经存在的一个Key
  1. # Lock keys here
  2. lock_keys( %hTestHash );
  3. # Recipe 5.4
  4. # We can still the keys before locked
  5. delete $hTestHash{ ONE };

  6. # Recipe 5.2  
  7. if( not exists $hTestHash{ ONE } ){
  8.         print "ONE deleted!\n";
  9. }
  10. # Recipe 5.6
  11. printHash( \%hTestHash);
复制代码
通过输出语句,我们看到在key锁住之后,被锁前的Key居然可以删除掉。

那我们能不能新增一个锁之前没有的Key呢?
  1. eval{
  2.         $hTestHash{ FOUR } = 4;
  3. };
  4. print "Illegal operation when the hash is locked:\n$@" if $@;
复制代码
这里我们插入FOUR => 4这条记录,但是被抛出异常了!表示似乎不能增加新的Key。那我们又问,刚刚我们删除掉的Key: ONE, 在锁之前它就存在,那它能不能现在又被加回来呢?我们尝试了下:
  1. # We can add the keys had been existed before the keys was locked
  2. eval{
  3.         $hTestHash{ ONE } = 1;
  4. };
  5. print "We can add the keys had been existed in hash before the keys were locked\n" if not $@;
  6. printHash( \%hTestHash );
复制代码
注意这里是if not $@。这表明我们insert成功了。所以lock_keys在这里的意思是,你可以修改,删除,添加锁之前就存在的Key, 但是绝对不能增加锁之前就没有的key!

接着我们用unlock_keys释放锁,现在我们又可以正常加新的记录了
  1. # Unlock keys now and insert new entry
  2. unlock_keys( %hTestHash );
  3. $hTestHash{ FOUR } = 4;
  4. printHash( \%hTestHash );
复制代码

论坛徽章:
0
5 [报告]
发表于 2012-08-21 20:46 |只看该作者
接着我们讲lock_hash。这个函数将整个Hash都锁住了,不可改动。
这里修改值,删除Key, insert新的值,都不可行。
  1. print "Testing of lock_hash\n";
  2. lock_hash( %hTestHash );
  3. eval{# We can't modify the value here
  4.         $hTestHash{ ONE } = 5;
  5. };
  6. print "We can't modify the value of key 'ONE', when it is locked:[$@]" if $@;
  7. eval{# Can't delete
  8.         delete $hTestHash{ ONE };
  9. };
  10. print "We can't delete key 'ONE' when the hash is locked:[$@]" if $@;
  11. eval{# Can't insert
  12.         $hTestHash{ ZERO } = 0 ;
  13. };
  14. print "We can't insert key 'ZERO' when the hash is locked:[$@]" if $@;
  15. printHash(  \%hTestHash );
  16. # Recover it
  17. unlock_hash( %hTestHash );
复制代码
用unlock_hash可以释放锁。这样Hash又可以正常操作了。

论坛徽章:
0
6 [报告]
发表于 2012-08-21 20:49 |只看该作者
明天我们讲lock_value。这个函数会有些细节,所以要稍微多说下。另外Python我目前还没有找到库函数对原生dict有这样的锁支持,虽然我们可以写个包装类出来,但是还是不能和Perl这样的功能相比。等我找到了合适的标准库,再来进行更新。

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
7 [报告]
发表于 2012-08-22 15:59 |只看该作者
坚持就是胜利...

论坛徽章:
0
8 [报告]
发表于 2012-08-22 17:06 |只看该作者
本帖最后由 sjdy521 于 2012-08-22 17:07 编辑

前几天还在看这个模块,想了解下内部的实现原理是什么,看的比较晕乎,实现的机制看似不像是和use field一样
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP