03 线程安全问题

一、什么时候会出现线程安全问题?

无线程安全问题:

1、在单线程中不会出现线程安全问题

2、java领域的线程安全问题,通常是全局变量或静态变量引起的,若每个线程对共享变量只有读操作,一般来说该变量是线程安全的,若有写操作,则需要考虑线程安全问题。

3、当多个线程执行一个方法,方法内部的局部变量并不是临界资源,因为方法是在栈上执行的,而Java栈是线程私有的,因此不会产生线程安全问题。

线程安全问题:

1、有多个线程时,同时访问同一个资源(一个对象,对象中的属性,一个文件,一个数据库等),会导致程序运行结果并不是想要的。

  举个简单的例子:

  现在有两个线程分别从网络上读取数据,然后插入一张数据库表中,要求不能插入重复的数据。那么必然在插入数据的过程中存在两个操作:

  1)检查数据库中是否存在该条数据;

  2)如果存在,则不插入;如果不存在,则插入到数据库中。

  假如两个线程分别用thread-1和thread-2表示,某一时刻,thread-1和thread-2都读取到了数据X,那么可能会发生这种情况:

  thread-1去检查数据库中是否存在数据X,然后thread-2也接着去检查数据库中是否存在数据X,结果两个线程检查的结果都是数据库中不存在数据X,那么两个线程都分别将数据X插入数据库表当中。

  这里面,这个资源被称为:临界资源(也有称为共享资源)。

二、如何解决线程安全问题?

通常是在访问临界资源的代码前面加锁,当访问完临界资源后释放锁,让其他线程继续访问。

2.1 单机

单机多线程情况,可以通过 synchronized 或者 Lock 进行加锁,是Java中提供的两种方式来实现同步互斥访问。

2.2 分布式系统

现在大部分应用都是采用分布式的方式进行部署,属于多进程的情况,这可以通过分布式锁、原子操作来解决。
a. 分布式锁的实现方式有 b. redis原子操作
  • 单命令:把多个操作在Redis中实现成一个操作,也就是单命令操作。Redis是使用单线程来串行处理客户端的请求操作命令的,所以,当Redis执行某个命令操作时,其他命令是无法执行的,这相当于命令操作是互斥执行的。
  • Lua脚本:把多个操作写到一个Lua脚本中,以原子性方式执行单个Lua脚本。

参考资料

多线程的安全问题

redis 高并发分布式锁实现

Java并发编程:Lock

posted @   zhegeMaw  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示