资讯专栏INFORMATION COLUMN

java浅谈线程安全之锁

summerpxy / 1902人阅读

摘要:分布式情况下多线程和线程很可能不在同一中,这样本地锁无法解决问题,这个时候分布式锁就出现了。那么直接加一个本地锁不就可以么,确实是这样的,代码变得线程安全了,但是这是一个悲观锁,创建对象对策效率就会变的奇低。

在java锁的知识中,我们首先要知道分布式锁和本地锁的概念。

1、本地锁:

在单进程的系统中,存在多个线程去同时操作某个共享变量时,就需要使用本地锁,最常用的关键字:synchronized

2、分布式锁:

在分布式系统中,我们知道会有多台服务器同时部署一个大项目,这样就是多进程对应的多线程问题。分布式情况下(多jvm),线程A和线程B很可能不在同一JVM中,这样本地锁无法解决问题,这个时候分布式锁就出现了。

常用技术方案:目前作者已经使用过Redis+Lua脚本、使用redis中setnx指令、使用redis自带成熟的框架Redisson框架去解决分布式锁问题。

3、本地锁应用之单例模式之懒汉单例模式

在引入锁之前我们先来看一个单例设计模式之懒汉单例模式:

package task4;public class LazySingle {    private static LazySingle instance = null;    private LazySingle() {        System.out.println("构造函数");    }    public static LazySingle getInstance() {        if(null == instance) {            instance = new LazySingle();        }        return instance;    }}class TestLazy {    public static void main(String[] args) {        LazySingle instance1 = LazySingle.getInstance();        LazySingle instance2 =  LazySingle.getInstance();        System.out.println(instance1 == instance2);    }}

运行结果:

直接学习上面代码我们发现这个代码是线程不安全的,原因是两步操作(先取值,在赋值),不具备原子性。

当多个线程访问这个方法时,必定会创建多个对象,这样这个代码就不是单例的。

那么直接加一个本地锁:synchronized不就可以么,确实是这样的,代码变得线程安全了,但是这是一个悲观锁,创建对象对策效率就会变的奇低。

怎么办呢?我们在仔细学习代码发现:return instance;这是一个原子性的操作,问题其实就是出在if(null == instance ) { instance == new LazySingle(); } 这明显就是一个先取值判断在赋值的过程,不是一个线程安全的。

在单例模式中,我们只需要创建一个对象,那么我们发现一开始对象不存在的时候一定会走if(null == instance ) {}

当多线程访问的时候就会有漏网之鱼进入这个代码块,所以我们发现只有第一次创建对象的时候是线程不安全的,其余后面n次获取对象都是安全的,都是直接return。

好?那怎么解决这个问题?采用双重判断加synchronized锁解决问题。

只锁第一次,后面的n次不锁,很妙,完美解决效率问题。也实现了单例模式。

4、分布式锁

分布式锁其实本质是一样的,只是因为分布式系统中,代码运行在多台机器,本地锁锁不住了,只能用分布式锁。

由于时间原因,后面有时间会多带带出一篇文章来应用分布式锁----以秒杀案例中的超买超卖问题和redis的缓存穿透为例子进行说明。

好啦,谢谢大家阅读,萌新文本不好哈。希望大家共同加油,把java从入门到入坟,走上人生巅峰。哈哈~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/119165.html

相关文章

  • Mysql系列之锁机制

    摘要:事务的隔离级别案例分析无索引行锁升级为表锁间隙锁的危害分析行锁定通过检查状态变量来分析系统上的行锁争夺情况优化建议页锁 一般一个程序满,从消耗的角度,一个是cpu,一个是IO,但有的时候mysql慢,是因为某条sql不小心把整个表给锁了。 什么是锁? 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除了传统的计算机资源(如CPU,RAM,I/O)的争用外,数据也是供很多...

    darcrand 评论0 收藏0
  • 浅谈Java并发编程系列(一)—— 如何保证线程安全

    摘要:比如需要用多线程或分布式集群统计一堆用户的相关统计值,由于用户的统计值是共享数据,因此需要保证线程安全。如果类是无状态的,那它永远是线程安全的。参考探索并发编程二写线程安全的代码 线程安全类 保证类线程安全的措施: 不共享线程间的变量; 设置属性变量为不可变变量; 每个共享的可变变量都使用一个确定的锁保护; 保证线程安全的思路: 1. 通过架构设计 通过上层的架构设计和业务分析来避...

    mylxsw 评论0 收藏0
  • 浅谈js单例模式

    摘要:单例模式说到单例设计模式,中经常使用的单例模式通常分两种,懒汉模式和饿汉模式懒汉模式简单写了下私有化构造函数在获取实例的方法中返回实例化对象虽然很多大佬都写过啦,但是小生为了加深记忆便再写一遍虽然实现了单例模式,但是未考虑到线程安全,多个线 java单例模式 说到单例设计模式,Java中经常使用java的单例模式通常分两种,懒汉模式和饿汉模式 懒汉模式 class singleDemo...

    draveness 评论0 收藏0
  • 浅谈Java中的同步

    摘要:在多线程的问题上面概念比较多,也需要慢慢理解,其实也在多线程的锁的上面做了很多优化,还有互斥同步和非互斥同步,还有很多概念,什么是自旋和自适应自旋,锁消除顺便提一下,上面的字符串拼接的例子就是用到了这种优化方式,锁粗化,我们下次再继续分享。 在我们平常的开发工作中,或多或少的都能接触到多线程编程或者一些并发问题,随着操作系统和系统硬件的升级,并发编程被越来越多的运用到我们的开发中,我们...

    YacaToy 评论0 收藏0
  • 浅谈双重检查锁定和延迟初始化

    摘要:非线程安全的双重检查锁这里看起来很完美,但是是一个错误的优化,代码在读取到不为的时候,引用的对象有可能换没有完成初始化,这样返回的是有问题的。 在Java多线程程序中,有时需要采用延迟初始化来降低初始化类和创建对象的开销,双重检查锁定是常见的延迟初始化技术,但它是一种错误的用法 双重检查锁的演进以及问题 使用syncronized实现 public synchronized stati...

    Shonim 评论0 收藏0

发表评论

0条评论

summerpxy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<