线程如何实现安全的?
首先线程安全的对象具有以下特征:对象本身已经封装了所有必要的正确性保障手段,对象的使用者不用考虑多线程的问题。
java的线程安全定义有哪些?
不可变:为int,float等基础类型前边加final是该对象的值不可变,在Map,类等对象前加final,是对象的引用不可变。String类型的数据本身是不可变的。
绝对的线程安全:比如Vector,类中属性大多都加了synchronized,但是还达不到绝对的线程安全。
相对的线程安全:大部分的线程安全类都是这样的比如,hashTable、Vector等
线程兼容:指的是对象本身是线程不安全的,但是调用端正确的调用手段可以达到线程安全的目的,比如Arraylist,HashMap等。
线程对立:指的是无论采取什么并发措施,都无法达到线程安全的目的,比如Thread类中的suspend()和resume(),可能会导致死锁。
线程安全如何实现?
1.阻塞同步(同步方法)
(1) synchronized 关键字是常见的阻塞手段,synchronized是java提供的原子性内置锁,并且成为监视器锁。synchronized编译之后会在代码块前后添加minitorenter和monitorexit指令,成功之后monitorenter会将锁计数器加一,monitorexit指令会将锁计数器减一,为0则释放锁,synchronized指令对同一个线程是可重入的:线程执行完之前,会阻塞后边的线程,适合锁少量的同步代码块
(2)java.util.concurrent中的可重入锁ReentrantLock与synchronized功能相似,添加了更多功能,主要是3点:
一是等待可中断(持有锁的线程长时间不释放的时候,等待的线程可执行其它操作),
二是可实现公平锁(构造参数的boolean值代表是否公平锁)(可根据等待锁的时间顺序依次获取锁,syncharonized是非公平锁)
三是可指定解锁条件(ReentrantLock可绑定多个Condition,只需要lock.newCondition()即可)
两个锁对比,synchronized在多线程高并发的情况下,性能下降的非常严重,ReentranLock是最佳选择,synchronized有很多要优化的地方。
2.非阻塞同步
这种乐观锁的同步策略需要将操作和冲突检测放在一个指令集里边
比较并交换(Compare And Swap)
CAS指令需要三个参数(V、A、B)V是内存地址,A是旧值,B是新值,当且仅当V符合A的值时候,cpu会将新值B更新到地址V,这是连续的原子操作
JDK1.5之后,在Java的sun.misc.Unsafe提供CAS操作,如:CompareAndSwapInt()、compareAndSwapLong()等
CAS的漏洞:“ABA问题”,原值A,地址目前也是A,但是无法确认A是否是被修改过的A,还是原来的A
3.无同步方案
一些代码天生就是线程安全的,不需要进行线程安全的操作:如可重入代码和线程本地存储
同步代码块
例如我们来重写incrementCounter():
public void incrementCounter() {
// 其他无需同步的操作
synchronized(this) {
counter += 1;
}
}
例子很简单,但它展示了创建同步代码块的原理。假设该方法有一些额外的、不需同步的业务,那我们只需用synchronized块包住需要同步的代码即可。
与同步方法不同,同步代码块需要指定内在锁锁定的对象,通常用this即可。
当然同步方法和同步代码块,可有效解决线程间的变量可视度问题,即便如此,普通类中的值有可能被CPU缓存。因此,即使使用同步技术,在变量被改变后,其他线程也有可能无法获取最新的变量值。
我们使用volatile防止这种情况出现
public class Counter {
private volatile int counter;
// 标准的构造方法/getter
}
volatile关键字告诉JVM和编译器,把counter变量存放在主内存中。这样有效保证JVM每次都会从/向主内存读取/写入counter变量,而非CPU缓存。
public class User {
private String name;
private volatile int age;
// 标准的构造方法/getter
}
以上例子里,JVM不仅会向主内存写入age变量,还会写入name变量到主内存。这样保证了两个变量的最新数值都保存在主内存中,更新变量的结果对其他线程均可见。
相似的,如果某个线程读取了volatile变量中的值,所有对该线程可见的变量,都会从主内存中读取数值。
volatile提供的这个特性,被称为一变量volatile,全员走内存(full volatile visibility guarantee)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通