线程安全总结

http://xxxzhi.github.io/2014/09/07/summary-of-thread-safety/


前几天,师兄上传图片的Android手机应用,每次传输图片到我的后台,都会出现一个问题,第一次传输总是传了一个已经乱码了的图片,然后重新传这张图片,才ok。然后我跟他一起检查代码,就发现了这个原因就是多线程导致的问题。

因为图片需要压缩,所以师兄开始的处理是每次拍完照,确定图片后,就开始启动一个线程压缩图片,以便到了最后,需要上传图片的时候,能够直接上传。这样就能够节省了不少时间了。但是在处理的时候,忽略了一个多线程的问题,就是在上传压缩后的图片的时候,你并不能保证已经完全压缩完了。因为最开始没有做任何处理,结果就导致了,上传的图片只是压缩过程中的一个中间图片罢了。两个线程同时对那张图片进行操作,一个写,一个读,结果就导致只读取了写的一半。

这个地方就完全体现出来多线程的困扰。当然,上面的问题很容易解决,用个标志量,判断是否已经压缩完全,否则的话,就让上传图片的进程等待。但是很多时候,往往是你自己都不知道发生了多线程竞争,不知道需要考虑线程同步。而且这种线程同步还是跟用户操作有关的,比如上面那个例子,假如用户拍完照后,看了一段时间再去上传图片,可能就没有任何问题了。

如何避免

其实遇到这种问题,就当是给自己提个醒,在老师教我们的时候,都说多线程很麻烦,很容易出问题,大家要注意。但是我们那时候根本就没有什么体会,到了最终自己编写项目的时候,有时候就会因为这些看似不经意的小地方,出现一些莫名其妙地,本来看似不会出现的问题。而且这种问题,如果没有经过强力的测试,你是无法发现的,这才是最最严重的问题。我看了网上一些人的介绍,并且结合自己的一些经历和思考,总结了下面一些东西:

  1. 在写多线程的时候,多留一颗心,脑子里面要有对每个线程执行的顺序印象,去思考,会不会有哪个地方出现线程安全的问题。一定要思路清晰。
  2. 对于那些可能出现问题的地方要多留一颗心,提防着它们,对于一些可能不会出现问题的,也给它加个保护,因为一方面,你会判断错误,另一方面,现在不会,不代表以后不会。
  3. 一个易错的细节:对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。

其实如何避免线程问题,其实就是自己去发现问题,而发现这些线程问题,印象中很多教材都有不少介绍,记得我那时候学习的时候,老师布置的作业也是这方面的问题。发现问题,简化了后,就是书本上面的问题了。比如说画图之类的。

线程同步的方式和机制

再介绍一下线程同步的方式与机制,其实这个我是也没有什么很深的印象的了,查了下资料。它主要有临界区、互斥量、信号量、事件这几种方式。

  • 临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
  • 互斥量:采用互斥对象机制。只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。
  • 信号量:它允许多个线程在同一时刻访问同一个资源,但是需要限制在同一时刻访问此资源的最大线程数目
  • 事件:通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作。
不同语言的线程同步

不同编程语言间,在线程同步使用上面是不相同的,本身C和C++就是操作系统主要的编写语言,C与上面四种方式更加相近。C主要有以下几个: - 互斥锁,像pthread_mutex_t结构 ,函数pthread_mutex_lock() … - 条件变量,pthread_cond_t结构,函数pthread_cond_wait(),pthread_cond_timedwait()等 - 信号灯,有这些函数:sem_init,sem_destroy,sem_post,sem_wait等 - 异步信号以及其他的一些同步方式

这些都主要在头文件 中,我前段时间在港中文实习的时候,因为要在Android里面,用C++写个Socket服务器,就经常需要跟各种线程方面的东西打交道,保持线程的同步。做这些东西需要很细致。

Java的线程同步使用比较多的一个关键字 synchronize 以及volatile。java中几乎已经将线程同步封装很好,所以使用起来会比C方便很多。但是千万别以为Java线程同步就这样而已。如果你想要应用好线程同步还是要认真领悟好Synchronize 跟 volatile,而且不同的使用方式,效率也会不一样。


我思故我在,我思故我在…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值