java线程安全的类6,java学习|图说多线程(一)那些孪生的线程(不)安全的类

本文为多线程第一篇,

不深入细节,

大体上聊一聊我们常用的类,

先来一张图感受下:

ca9784028a1c855ab2f096ac8449992f.png

在上面三组类中,开发时我们大都是使用的上面的,如使用StringBuilder做String拼接。 使用ArrayList存储数据库返回的一组数据, 用HashMap传参等等。

因为现在开发大都是在SpringMVC下开发,全局变量都是一些Manager, Service,Mapper之类的。 然后我们的List, Map变量一般都是在方法里面新建,使用,返回。在jvm中,局部变量存在于vm栈的每个方法的栈帧中,这个线程所私有的,不会引发线程安全问题,所以我们用上面的或是下面的程度大都可以正确的运行,也正是这样,也让我们一直没有机会深入到他们之中,看看他们有什么不一样

StringBuilder VS StringBuffer , 对比方法 append()

4026917df224fcc098b2e39abeec1f6f.png

ArrayList VS Vector , 对比方法 add()

cab425491742b871ac0c0c6c8a9e6654.png

HashMap VS Hashtable , 对比方法 put()

f1d8696b9f46f861a71dfe1fceeeb015.png

细心的小伙伴们估计已经注意到了,

两个类的这些方法中,

方法名,参数,返回值,

和实现都大体上差不多,

只是在方法声明上有些差别:

synchronized.synchronized放在非static方法是,

是对当前实例加锁,

例:

Hashtable table = new Hashtable<>();

table.put("java","技术大本营");

table.get("java");

de1e4fafa5937bf2f7cbdf253182ca9f.png

我们在使用table 这个实例时,线程A要使用table的get方法,就要先等别的线程使用完put方法。这种读写相间的说是为了保证数据一致加个锁倒也无可厚非,但是,如果两个线程都是使用get方法,也是同一时间只有一个线程能读取。所以现在在项目中很少看到后Vector 和 hashtable出现了。

从日常开发中,我们不难总结出,读 其实是不需要加锁的,只有写的时候才需要加锁,而且写的时候也不至于从方法第一行就加锁,可以只对更改的那几行加锁就可以了,或者对数据分段,对需要修改的那一段数据加锁。 整体的思路就是,降低锁的粒度。 还有更厉害的就是直接不加锁了,大家一起去竞争,但改之前必须要和自己以前拿到的数据对比,中间没有人动过才能改。

相信已经有小伙伴通过上段的描述想到了对应的例子,如ConcurrentHashMap , CAS等等 , 这些是后话,今天先和大家一起认识一些孪生的线程(不)安全的类。

总结:通常一提到线程安全,大家都会第一时间想到加锁,但对谁加锁,什么时候加锁,是个值得考量的问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值