synchronized
? 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:JavaEE
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖
synchronized
1. 特性
1.1 互斥
synchronized 会起到互斥效果,某个线程执?到某个对象的 synchronized 中时,其他线程如果也执?到同?个对象synchronized 就会阻塞等待。
synchronized?的锁是存在Java对象头?的。可以粗略理解成,每个对象在内存中存储的时候,都存有?块内存表?当前的 “锁定” 状态(类似于厕所的 “有?/??”)。
如果当前是 “??” 状态,那么就可以使?,使?时需要设为 “有?” 状态;如果当前是"有?"状态,那么其他??法使?,只能排队。
针对每?把锁,操作系统内部都维护了?个等待队列。当这个锁被某个线程占有的时候,其他线程尝试进?加锁,就加不上了,就会阻塞等待,?直等到之前的线程解锁之后,由操作系统唤醒?个新的线程,再来获取到这个锁。
注意:
- 当上?个线程解锁之后,下?个线程并不是?即就能获取到锁,?是要靠操作系统来 “唤醒”,这也就是操作系统线程调度的?部分?作。
- 假设有 A B C 三个线程,线程 A 先获取到锁,然后 B 尝试获取锁,然后 C 再尝试获取锁,此时 B 和 C都在阻塞队列中排队等待。但是当 A 释放锁之后,虽然 B ? C 先来的,但是 B 不?定就能获取到锁,?是和 C 重新竞争,并不遵守先来后到的规则。
1.2 可重入
synchronized 同步块对同?条线程来说是可重?的,不会出现??把??锁死的问题。
什么情况下,会把自己锁死?
?个线程没有释放锁,然后?尝试再次加锁。
// 第?次加锁,加锁成功
// 第?次加锁,锁已经被占?,阻塞等待。
按照之前对于锁的设定,第?次加锁的时候,就会阻塞等待。直到第?次的锁被释放,才能获取到第?个锁。
但是释放第?个锁也是由该线程来完成,结果这个线程已经躺平了,啥都不想?了,也就?法进?解锁操作。这时候就会 死锁,这样的锁也就称为 不可重入锁。
在可重?锁的内部, 包含了 “线程持有者” 和 “计数器” 两个信息。
- 如果某个线程加锁的时候,发现锁已经被?占?,但是恰好占?的正是??,那么仍然可以继续获取到锁,并让计数器自增。
- 解锁的时候计数器递减为 0 的时候,才真正释放锁。(才能被别的线程获取到)
2. 使用
synchronized 本质上要修改指定对象的 “对象头”。从使??度来看,synchronized 也势必要搭配?个具体的对象来使?。
2.1 修饰代码块
明确指定锁哪个对象
//锁任意对象
public class SynchronizedDemo {
private Object locker = new Object();
public void method() {
synchronized (locker) {
}
}
}
//锁当前对象
public class SynchronizedDemo {
public void method() {
synchronized (this) {
}
}
}
2.2 修饰普通方法
锁的 SynchronizedDemo 对象
public class SynchronizedDemo {
public synchronized void methond() {
}
}
2.3 修饰静态方法
锁的 SynchronizedDemo 类的对象
public class SynchronizedDemo {
public synchronized static void method() {
}
}
两个线程竞争同?把锁,才会产?阻塞等待。
两个线程分别尝试获取两把不同的锁,不会产?竞争。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!