推进网站集约化建设的做法,网站建设实训个人总结,教你免费开网店,有关计算机网站建设的论文⭐ 作者#xff1a;小胡_不糊涂 #x1f331; 作者主页#xff1a;小胡_不糊涂的个人主页 #x1f4c0; 收录专栏#xff1a;JavaEE #x1f496; 持续更文#xff0c;关注博主少走弯路#xff0c;谢谢大家支持 #x1f496; synchronized 1. 特性1.1 互斥1.2 可重入 … ⭐ 作者小胡_不糊涂 作者主页小胡_不糊涂的个人主页 收录专栏JavaEE 持续更文关注博主少走弯路谢谢大家支持 synchronized 1. 特性1.1 互斥1.2 可重入 2. 使用2.1 修饰代码块2.2 修饰普通方法2.3 修饰静态方法 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() {}
}两个线程竞争同⼀把锁才会产⽣阻塞等待。 两个线程分别尝试获取两把不同的锁不会产⽣竞争。