java保证线程安全的方式有哪些?

导致线程不安全的原因有,主要有三个:
1.原子性:一个或者多个操作在CPU执行过程中被中断
2.可见性:一个线程共享变量的修改,导致另一个线程不能立即看到
3.有序性:程序执行的顺序没有按照代码的先后顺序执行

java平台编译器:静态编译器javac(加载后直接执行),动态编译器jit(.class文件再编译成机器码,可能会对指令进行重排序,指定的内存访问顺序跟源代码编写不一致)。

针对原子性,
1.JDK提供的Atomic类,通过CAS来保证原子性。比如AtomicInteger、AtomicLong、AtomicBoolean等。
2.java提供了各种锁机制,比如synchronized关键字。

针对可见性,
1.使用synchronized关键字加锁来解决
2.java提供volatile关键字,比synchronized关键字性能更优

针对有序性,
1.使用synchronized关键字定义同步代码块或同步方法
2.通过lock接口来保证有序性

同时,针对不同的应用场景,还可以使用分布式锁来实现线程安全,比较常用的分布式锁实现方式有,基于数据库实现的分布式锁(不常用,除非是单数据库,但是不便于后期扩展),基于redis实现的分布式锁、基于zookeeper实现的分布式锁。还有一种就是使用ThreadLocal来进行线程隔离。ThreadLocal类是作为线程内部的局部变量而提供的。让这些变量在多线程环境下访问(get/set)时能保证各个线程里的变量相对独立于其他线程内的变量。通过ThreadLocal创建的变量只能被当前线程访问,对其他线程不可见,故别的线程无法访问和修改,也就是说:对线程公有化变成对线程私有化。事实上每个线程中都有一个ThreadLocal变量副本。
相比于锁的性能:
java在使用锁的使用中会导致运行效率降低,ThreadLocal的使用彻底避免对共享资源的竞争,同时又可以不影响效率。ThreadLocal采⽤了“以空间换时间”的⽅式,为每⼀个线程都提供⼀份变量的副本,从⽽实现同时访问⽽互不影响,但因为每个线程都维护着⼀份副本,对内存空间的占⽤会增加。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值