多线程高并发下的线程安全怎么实现

首先举一个例子
现在有5个用户同时访问业务需要生成5个唯一订单ID并存入数据库

这是一个公共的生成ID的类,生成的规则是【当前时间+用于自增的全局变量】(不要在意这个方式的弊端,只是用来举个栗子~)

我们跑一下试试

可以看到竟然有两个一模一样的ID,这是万万不能允许发生的情况
为什么会发生这种情况呢,是因为多个线程在同一时间访问了这个方法,然后修改了这个int变量,上一个线程还没来得及做完所有操作,int值就被另个线程给修改了

下面讲解如何解决问题

基于JVM解决:
1.使用Synchronized解决问题
 public class Test{
     //创建锁对象
    static synchronizedTest instance=new synchronizedTest();
    public void test() {
        //省略其他的耗时操作。。。
        //使用同步代码块对方法内的代码进行同步操作,锁对象为instance
        synchronized(instance){
           //需要执行的代码。。。
        }
    }
}
1234567891011
给生成ID的代码加上同步代码块,成功解决问题

使用同步代码块的作用是:同一时刻,只有一个线程可以执行该代码块

除了第一种方法外,还可以使用第二种方法解决问题
2.使用Lock锁解决问题
public class LockTest {
    private Lock lock = new ReentrantLock();
 
    //需要参与同步的方法
    private void test(Thread thread){
        //获取锁,如果锁被暂用则一直等待
        lock.lock();
        try {
            System.out.println("获得了锁");
        }catch(Exception e){
            //打印异常
            e.printStackTrace();
        } finally {
            System.out.println("释放了锁");
            //释放锁
            lock.unlock();
        }
    }
 
12345678910111213141516171819
给生成ID的代码加上Lock锁,成功解决问题


这两种方法都是为了解决同步问题,那么他们的区别是什么呢?

这里提供一个表来方便做对比(来源:https://blog.csdn.net/qq_39521554/article/details/81130442)
类别
            synchronized
            Lock
        存在层次
            Java的关键字,在jvm层面上
            是一个类
        锁的释放
            1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁
            在finally中必须释放锁,不然容易造成线程死锁
        锁的获取
            假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待
            分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待
        锁状态
            无法判断
            可以判断
        锁类型
            可重入 不可中断 非公平
            可重入 可判断 可公平(两者皆可)
        性能
            少量同步
            大量同步
        

谈谈我的看法:
两者有一个很大的区别就是Synchronized是自动释放锁的,而ReentrantLock需要手动通过unlock()释放,如果没有处理好就很容易死锁
其次,ReentrantLock锁机制要比Synchronized更好一些,比如Synchronized因IO等问题被阻塞了,但是又没有释放锁,其他线程便只能干巴巴的等着,ReentrantLock有机制可以使线程不无限期等待而Synchronized不可以

两种同步方式的使用建议:
Synchronized和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面3种需求
1.某个线程在等待一个锁的控制权的这段时间需要中断
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程
3.具有公平锁功能,每个到来的线程都将排队等候
————————————————
版权声明:本文为CSDN博主「_MoLi_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/z806899669/article/details/99067176

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值