关于并发性能和并发安全随想

一直以来,我理解的并发编程包括两个方面,一个是并发性能,另一个则是并发安全。

在并发性能上,通过具体的编码能做的事情不多,从本质上来说,一些并发编程的编码方式比如锁机制等必然会降低系统吞吐量即降低性能,当然是无锁快,我们能做的只是尽力提高并发性能。其实提高并发性能的主要方式还是通过一些中间件以及合理的架构方式。比如用Redis实现缓存以及分布式甚至微服务等项目架构,这些途径提高并发性能卓有成效。相比之下,想通过苛求编码的细节去提高并发性能显得微不足道,有时候为了考虑代码的可读性以及编码风格等因素甚至可以放弃。

在并发安全上,我理解的地方也有两个方面,一个是涉及到多线程工作内存与主内存的读写造成的并发安全问题,另一个则是涉及到数据库,多线程同时修改表中一行等这些行为,可能造成错误修改等情况。有一个需要注意一下,一个进程是不会造成表死锁的,因为一个进程下的多个线程的事务会有事务等待,但是不同进程中的线程同时操作表中一行就可能造成表死锁,比如程序中操作表的时候触发表的触发器就可能造成表死锁,因为这里有两个进程,一个是程序的主进程,而触发器是数据库的进程。

前文说到的并发安全两个方面都可以通过加锁的方式去解决,同时只允许一个线程工作就没问题了,也都可以通过无锁的方式解决,前者有CAS机制,后者有乐观锁。其实这种说法不准确,因为CAS就是乐观锁的一种,而synchronized或者lock等这些锁机制也可以称为悲观锁,乐观锁和悲观锁是两个大概念,只不过在数据库中称为乐观锁和悲观锁称习惯了。

重点总结一下数据库的乐观锁和悲观锁。

悲观锁很简单,有两大类分别为共享锁和排他锁,使用悲观锁要写具体的SQL语句,即悲观锁是数据库自带的,体现在SQL中,通过SQL语句可以实现增删改查的时候锁住一行等操作,具体的语句书写可以积累。

乐观锁一般是针对更新操作而言的。乐观锁不是数据库自带的,需要自己去设计表结构,通常是这么实现的:先给表加一个字段version,每次对该表的操作都会将对应行的version加1。如果有一个更新操作,操作之前先查出该行的version,再update的时候加一个where条件判断version是否相同。如果version相同就说明在这段时间内没有其他线程修改这行,即可以更新。如果version不同就说明在这段时间内这行被其他线程修改了,即不可以更新,where条件判断不成立也不会去执行这条更新sql了。

猜你喜欢

转载自blog.csdn.net/weixin_42447959/article/details/83758933