并发情况下如何保证数据安全,一直都是开发人员每天都要面对的问题,稍不注意就会出现数据异常,造成不可挽回的结果。笔者根据自己的实际开发经验,总结了下面几种保证数据安全的技术手段:

  1. 无状态

  2. 不可变

  3. 安全的发布

  4. volatile

  5. synchronized

  6. lock

  7. cas

  8. threadlocal

一.无状态

我们都知道只有多个线程访问公共资源的时候,才可能出现数据安全问题,那么如果我们没有公共资源,是不是就没有这个问题呢?

public class NoStatusService {public void add(String status) {System.out.println("add status:" + status);}public void update(String status) {System.out.println("update status:" + status);}
}

二.不可变

如果多个线程访问公共资源是不可变的,也不会出现数据的安全性问题。

public class NoChangeService {
public static final String DEFAULT_NAME = "abc";public void add(String status) {System.out.println("add status:" + status);}
}

三.安全的发布

如果类中有公共资源,但是没有对外开放访问权限,即对外安全发布,也没有线程安全问题

public class SafePublishService {
private String name;public String getName() {
return name;}public void add(String status) {System.out.println("add status:" + status);}
}

四.volatile

如果有些公共资源只是一个开关,只要求可见性,不要求原子性,这样可以用volidate关键字定义来解决问题。

public class FlagService {public volatile boolean flag = false;public void change() {
if (flag) {System.out.println("return");
return;}       flag = true;System.out.println("change");}
}

五.synchronized

使用JDK内部提供的同步机制,这也是使用比较多的手段,分为:方法同步 和 代码块同步,我们优先使用代码块同步,因为方法同步的范围更大,更消耗性能。每个对象内部都又一把锁,只有抢答那把锁的线程,才能进入代码块里,代码块执行完之后,会自动释放锁。

public class SyncService {private int age = 1;public synchronized void add(int i) {age = age + i;        System.out.println("age:" + age);}public void update(int i) {synchronized (this) {age = age + i;                          System.out.println("age:" + age);}    }
}

六.lock

除了使用synchronized关键字实现同步功能之外,JDK还提供了lock显示锁的方式。它包含:可重入锁、读写锁 等更多更强大的功能,有个小问题就是需要手动释放锁,不过在编码时提供了更多的灵活性。

public class LockService {
private ReentrantLock reentrantLock = new ReentrantLock();
public int age = 1;public void add(int i) {
try {reentrantLock.lock();age = age + i;           System.out.println("age:" + age);} finally {reentrantLock.unlock();        }    }
}

七.cas

JDK除了使用锁的机制解决多线程情况下数据安全问题之外,还提供了cas机制。这种机制是使用CPU中比较和交换指令的原子性,JDK里面是通过Unsafe类实现的。cas需要四个值:旧数据、期望数据、新数据 和 地址,比较旧数据 和 期望的数据如果一样的话,就把旧数据改成新数据,当前线程不断自旋,一直到成功为止。不过可能会出现aba问题,需要使用AtomicStampedReference增加版本号解决。其实,实际工作中很少直接使用Unsafe类的,一般用atomic包下面的类即可。

public class AtomicService {
private AtomicInteger atomicInteger = new AtomicInteger();public int add(int i) {
return atomicInteger.getAndAdd(i);}
}

八.threadlocal

除了上面几种解决思路之外,JDK还提供了另外一种用空间换时间的新思路:threadlocal。它的核心思想是:共享变量在每个线程都有一个副本,每个线程操作的都是自己的副本,对另外的线程没有影响。特别注意,使用threadlocal时,使用完之后,要记得调用remove方法,不然可能会出现内存泄露问题。

public class ThreadLocalService {
private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();public void add(int i) {Integer integer = threadLocal.get();threadLocal.set(integer == null ? 0 : integer + i);}}

总结

本文介绍了8种多线程情况下保证数据安全的技术手段,当然实际工作中可能会有其他。技术没有好坏之分,主要是看使用的场景,需要在不同的场景下使用不同的技术。

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

这8种保证线程安全的技术你都知道吗?相关推荐

  1. SQLite第三方框架FMDB的使用,以及使用FMDatabaseQueue保证线程安全

    2019独角兽企业重金招聘Python工程师标准>>> (1)下载地址:https://github.com/ccgus/fmdb (2)注意点 --语句可以带分号":&q ...

  2. 它又来了!C**HashMap是如何保证线程安全的?会用不就完了?

    欢迎关注方志朋的博客,回复"666"获面试宝典 阅读此篇文章,你需要有以下知识基础 Java内存模型,可见性问题 CAS HashMap底层原理 我们知道,在日常开发中使用的Has ...

  3. 多线程—线程池Executor框架及四种常用线程池

    池化技术应用:线程池.数据库连接池.http连接池等等. 池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率. 使用线程池的好处: 降低资源消耗:通过重复利用已创建的线程降低线程创建和 ...

  4. 按照顺序执行_问一个多线程的问题:如何才能保证线程有序执行?

    面试的时候你是否经常被问到这样的问题: 你一般通过什么方式去控制线程的执行顺序? 碰到这样的问题,我的内心其实是很抵触的! 开什么玩笑?我怎么会控制它呢?我为什么要控制它? 其实不用慌,这个问题并不难 ...

  5. 解析ThreadPoolExecutor类是如何保证线程池正确运行的

    摘要:对于线程池的核心类ThreadPoolExecutor来说,有哪些重要的属性和内部类为线程池的正确运行提供重要的保障呢? 本文分享自华为云社区<[高并发]通过源码深度解析ThreadPoo ...

  6. ConcurrentHashMap是如何保证线程安全的,你知道么?

    点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/qq_41737716/ article/details/90549847 前言 阅读此篇文章,你需要有以下知识基础 Java内 ...

  7. 聊聊保证线程安全的10个小技巧

    `` 前言 对于从事后端开发的同学来说,线程安全问题是我们每天都需要考虑的问题. 线程安全问题通俗的讲:主要是在多线程的环境下,不同线程同时读和写公共资源(临界资源),导致的数据异常问题. 比如:变量 ...

  8. 精妙绝伦的并发艺术品 — ConcurrentHashMap是如何保证线程安全的

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 后台回复"k8s",可领取k8s资料 | 前言 阅读此 ...

  9. ConcurrentHashMap 是如何保证线程安全的,你知道么?

    点击下方"IT牧场",选择"设为星标" blog.csdn.net/qq_41737716/article/details/90549847 01.前言 02. ...

最新文章

  1. CSS实现 全兼容的多列均匀布局问题
  2. poi向word插入图片_如何使用word裁剪图片图形?如何使用word修整图片?
  3. FineReport单行与数据库交互的方法
  4. Sublime Text 3 配置和使用方法
  5. Application Request Routing (ARR) TIME OUT 502
  6. cnpm 网络不能连接_5G网络那么牛,能打电话吗?(连载二)
  7. LaTeX Cookbook by Eric
  8. 微信客服我是这样管理的
  9. 第二次软件工程作业——模仿节奏大师官网制作的网页
  10. 如何用MATLAB加速,使用MATLAB加速C/C++算法开发
  11. Feign客户端415错误:FeignException$UnsupportedMediaType: [415 ]
  12. usbos在服务器上不能引导,USBOS V3.0.2021.07.10
  13. Java 正则表达式之提取数字
  14. Django前后端分离概念解析
  15. VR广告:通过“虚拟房间”广告在VR中体验Lionsgate的JIGSAW
  16. 使用阿里云创建个人云盘
  17. VS2015+opencv3.1+WIN7 计算机中丢失MSVCR120D.dll错误解决方法
  18. win10系统nfs服务器搭建
  19. 蒋晓海:Testin云测,如何让应用更有价值
  20. 康复医疗 趋势引领新蓝海

热门文章

  1. php cli输出百分比,CLI模式。能不能修改已经输出的内容?
  2. background 渐变_今日重点:April安卓渐变黑。| 明日日程:BUG修复。
  3. Cisco ftp linux 权限,在Cisco设备上利用FTP传IOS文件
  4. mysql21_mysql2
  5. bootstrap模态框 遮挡_Bootstrap Modal遮罩弹出层
  6. androidstudio在mainactivity实现监听器借口无法抽象_趣操作,Tomcat如何实现一键式启停?
  7. 七、Forword(请求转发)与Redirect(重定向)
  8. 支付系统中订单redis防重的使用
  9. 二进制指数类型退避算法
  10. openvas 配置遇到的问题