synchronized 关键字 - 监视器monitor lock

目录

1.synchronized的特性

1.1互斥

1.2可重入

2.synchronized 使用示例

2.1修饰代码块:明确指定锁那个对象

2.2直接修饰普通方法:锁的SynchronizedDemo 对象

2.3修饰静态方法:锁的SynchronizedDemo 类的对象

3.Java标准库中的线程安全类


1.synchronized的特性

1.1互斥

synchronized会起到互斥效果,某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象synchronized就会阻塞等待。

  • 进入synchronized 修饰的代码块,相当于加锁。
  • 退出synchronized 修饰的代码块,相当于解锁。

 synchronized用的锁是存在java对象头里的。

一个线程先上了锁,其他的线程只能等待这个线程释放

理解“阻塞等待”

针对每一把锁,操作系统内部都维护了一个等待队列,当这个锁被某一个线程占有的时候,其他线尝试进行加锁,就加不上了,就会阻塞等待,一直等到之前的线程解锁之后,由操作系统唤醒一个新的线程,再来获取到这个锁。

注意:

  • 上一个线程解锁之后,下一个线程并不是立即就能获取到锁,而是要靠操作系统来唤醒,这也就是操作系统线程调度的一部分工作。
  • 假设由ABC三个线程,线程A先获取到锁,然后B尝试获取锁,然后C再尝试获取锁,此时B和C都在阻塞队列中排队等待,但是当A释放锁之后,虽然B比C先来的,但是B不一定就能获取到锁,而且都是和C重新竞争,并不遵守先来后到的规则。

synchronized的底层是使用操作系统的mutex lock实现的。

1.2可重入

synchronized 同步对同一条线程来说是可重入的,不会出现自己把自己锁死的问题;

理解“把自己锁死”

一个线程没有释放锁,然后又尝试再次加锁。

第一次加锁,加锁成功。

lock();

第二次加锁,所已经被占用,阻塞等待。

lock();

按照之前对于锁的设定,第二次加锁的时候,就会阻塞等待,直到第一次的锁被释放,才能获取到第二次锁,但是释放第一个锁也是由该线程来完成的,结果这个线程已经躺平了,也就无法进行解锁操作,这时候就会死锁。

java中的synchronized 是可重入锁,因此没有上面问题。

for (int i = 0; i < 50000; i++) {
 synchronized (locker) {
 synchronized (locker) {
 count++;
 }
 }
}

在可重入锁的内部,包含了“线程持有者”和“计数器”两个信息。

  • 如果某个线程加锁的时候,发现锁已经被人占用,但是恰好占用的是自己,那么仍然可以继续获取到锁,并上计数器自增。
  • 解锁的时候计数器递减为0,才真正释放锁(才能被别的线程获取到)。

2.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() {
 }
}

我们重点理解,synchronized锁是什么。两个线程竞争同一把锁,才会产生阻塞等待。

两个线程分别尝试获取两把不同的锁,不会产生竞争。 

3.Java标准库中的线程安全类

java标准库中很多都是线程不安全的,这些类可能会涉及到多线程修改共享数据有没,又没有

任何加锁措施。

ArrayList

LinkedList

HashMap

TreeMap

HashSet

TreeSet

StringBuilder

但是还是有一些线程是安全的,使用了一些锁机制控制。

Vector    HashTable    ConcurrHashMap  StringBuffer

StringBuffer的核心方法都带有synchronized。

还有的虽然没有加锁,但是不涉及“修改”,仍然线程是安全的。

  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值