学校里学不到的C语言教程之7自动解锁引出

北京中科医院骗人 http://m.39.net/pf/a_4892467.html

今天我们要说的话题可能对于初学都来说涉及到的知识点太多了一点。要讨论这个问题大家应该已通过其他书籍学习了以下知识点:线程、异常、线程锁。这些知识都是实际工作中必须要掌握的,除了异常的知识我们前面已经特别详解过了以外,其他的知识我并不打算详解,因为基本上都可以从其他书籍学到,不过都是很重要的,大家应该认真掌握。我们只简单说一下注意事项。

当你真正进入程序员工作以后,一个不可避免的问题是一定要面对的:那就是线程。特别是对于C/C++这些传统的语言来说是没有封装到让使用者感觉不到线程的地步的(比如php程序员就不需要知道线程存在),我们必须处理。关于线程要提示大家的是在一些跨平台的框架比如QT中是有线程封装的,因为各个平台下的线程函数略有区别;另外就是线程锁学习互斥量就可以了,至于windows上的什么信号量没有必要太了解,或者说可以了解,但请在实际工作中使用互斥量,我知道会有很多有经验的人看到这里会反对,不过我想说的是那是因为你服务器程序写得不够多。另外还有一点我必须另外用下一段文字来进行说明。

不要在线程中直接操作gui控件,无论是在windows下还是linux下还是在手机上!这个观点已经越来越为大多数框架所使用,实际上早期的书籍中是说有线程中操作gui的,而且象windows的gui实际上也是线程安全的。只能说是程序引入线程后开发出错的可能性就指级上升,所以干脆现在的框架就这样注明了,就象现在的安卓程序已经不允许在主线程中操作socket了一样的:其实不是不能,而是对初学者赤说太易错了。那么gui中如何反映线程中产生的变化呢?现在的推荐做法是这样:线程操作各种变量,而gui定时去看一下数据变化了就显示出来,而不是线程中的数据变化了线程直接去修改gui控件上的显示内容(gui定时查看这里也有可能改成由线程发送一个通知告诉gui数据变化了)。

这时就会有一个经典的示例出来,显示数据在不同线程中造成的竞争问题,经典的教程做法是:开几个线程大家去修改某个int数值,然后再printf出来,然后告诉大家线程的执行顺序是不定的。这个做法隐藏了一个巨大的安全隐患,初学者把这个整数改成字符串的话程序十有八九要崩溃退出。这是因为这些示例为了简单忽略掉了线程访问变量前需要加锁的事实。大家不愿意把加锁写上去主要是因为线程锁的函数也是各个平台下有所不同的,要写的话代码就太多了。至于为什么访问int可以我们这篇文章就不解释了,总之大家记住无论访问什么正确的方式就是要先加锁定就行了。

说到加锁,知道的同学一定明白,加锁后一定要解锁,否则再次锁定后程序就不能动弹了。这个加解锁必须成对出现的问题在程序写作过程中很容易出错,我就出错过很多次。经过多次血的教训,我总结出了两种解锁的方式,第一种在各种语言中都通用,专治各种遗忘:牢记加解锁时一定要跟tryfinally块。这里就要给各种初学者们说明了:finally关键字在大多数现代语言里都有,它的作用是保证一个函数无论什么原因退出时都会跳到finally的块中执行然后才退出函数。这样我们就可以利用这个特性,将解锁代码写在finally里保证解锁一定会执行了,写上一个锁定时赶紧跟一个finally解锁,然后再写具体的代码逻辑就能解决问题了。用以下例子来说明这个finally特性:

有错误时一样会被执行

这段代码的执行效果如下:

执行结果

大家可以看到即使访问了错误的内存导致程序崩溃,但finally中的代码仍然执行了。初学者们肯定很郁闷:我怎么从来没看到C/C++里说到这个啊。我们把这段代码放到gcc里执行就明白为什么了:根本执行不了...因为这个就不是C/C++标准中的东西,而是VC的扩展。这实在不能怪VC破坏标准,因为语言设计里就没有这个东西,你让微软怎么办?事实上bcb也有类似的扩展,甚至gcc里也有第三方的扩展支持这个特性。

gcc不支持finally

那么假如我正好用的是linux下的gcc又不信任那些第三方代码怎么办呢?这就要提作者总结的第二种解锁的方法了,不过这也不是我的发明,是在一家做嵌入linux的公司中的做法,他们的做法非常简单:就是利用了C++标准中关于析构函数一定要保证执行的特性,在锁定时将锁告诉一个临时类,在临时类的析构函数中解锁就行了。这种办法也不错,可惜大多数语言没有自动调用析构函数这种做法,而且纯C里也没法用。不过现在很多项目都将编译器由gcc改为苹果的LLVM/Clang了,大家在走投无路的情况下可以试试苹果的编译器,也是非常非常出色的。

好了,希望以上的知识对大家有用。




转载请注明:http://www.aierlanlan.com/rzdk/2253.html

  • 上一篇文章:
  •   
  • 下一篇文章: