深入了解Java虚拟机学习之--如何实现线程安全?

一、互斥同步
1.同步:在多个线程并发访问共享数据时,保证共享数据在同一个时刻只被一个(或是一些,使用信号量的时候)线程使用。
2.互斥:是实现同步的一种手段,主要有以下:
临界区,互斥量,信号量
互斥是手段,同步是目的
3.在Java中实现互斥同步
synchronized关键字:在编译前后会在同步块的前后分别形成monitorentry和monitorexit这两个字节码指令,他们俩都需要一个reference类型的参数来知名要锁定和解锁的对象
ReentrantLock:支持锁重入,还支持等待中断,公平锁(synchronized锁是非公平的)是指按照申请锁的时间顺序进行分配,而ReentrantLock则支持公平锁,还支持锁绑定多个条件,可以同时绑定多个condition对象。
二、非阻塞同步
互斥同步又叫阻塞同步,是一种悲观的并发策略,总是认为只要不做正确的同步措施,就肯定会出现问题,即:无论是否出现共享数据的竞争,都会给资源加锁,用户态核心态转换,维护锁计数器,检查被阻塞的线程是否需要唤醒操作。
非阻塞同步是一种乐观的并发处理策略,是一种基于冲突检测的乐观并发处理,如果共享数据没有出现 其他竞争,则操作成功,所以这有一种侥幸的心理,但是当出现竞争是,那就才去补救措施(不断重试,直到成功)。
三、无同步方案
并不是实现线程安全就一定要进行同步,同步只是保证共享数据争用时的正确性的手段,如果不涉及共享数据的话,就不需要同步。
以下的两种代码天生就是线程安全的。
1.可重入代码
如果一个方法,返回结果是可以预测的,只要输入了相同的数据就能返回相同的结果,就符合可重入性。
特征:不依赖存储在堆上的数据和共用的系统资源,用到的状态量都由参数中传入,不调用非可重入的方法等。
2.线程本地存储
将共享数据的可见范围限制在在同一个线程中。
举例:生产者消费者模式中,消费者的消费过程,尽量在一个线程中完成;还有,web中一个请求对应一个服务器线程。
Java中,如果一个变量要被某线程独享,可以使用ThreadLocal类,每个线程的Thread对象中都有一个ThreadLocalMap对象,该对象中存储了一组以threadLocalHashCode为键,以本地线程变量为值的k-v对象。ThreadLocal对象就是当前线程的ThreadLocalMap的访问入口,每个ThreadLocal对象都包含了一个独一无二的ThreadLocalHashCode值,使用它就可以找到对应的本地变量。

    原文作者:java虚拟机
    原文地址: https://blog.csdn.net/fromddd/article/details/76849993
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞