操作系统——synchronized详解

目录

一、特性

1、互斥性

2、不可中断性

3、可重入性

二、使用

1、修饰普通方法

2、修饰静态方法

3、修饰代码块

三、锁机制


一、特性

1、互斥性

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

在同一时刻只允许一个线程持有某个对象的锁,此时只有一个线程使用该代码块。通过这种特性实现了多线程的协调机制。因此互斥性也成为了操作的原子性。

当已经有线程获取到该对象的锁时,其他线程也执行到该对象的被synchronized所修饰的方法也想获取锁进行加锁操作。但由于互斥性无法获取该锁,此时其他线程就会进入阻塞等待状态,直到之前的线程解锁后,其他线程才有机会获得该锁。

注:synchronized是非公平锁,并不会遵守先来后到的规则,而是同时竞争。是否能获得锁还得看操作系统的调度

2、不可中断性

当线程执行到的对象的锁被其他线程获得后,如果当前线程还想获得该锁,就只能进行阻塞等待,直到已获得该锁的线程释放锁后再尝试去获得锁。

3、可重入性

当一个线程请求另一个线程持有的锁时,请求的线程会阻塞,这是synchronized的不可中断性。但当线程去获取自己所拥有的锁时会请求成功而不会阻塞,这就是锁的可重入性

重入的原理:每个锁关联一个计数器和持有者线程,当计数器为0时候,这个锁被认为是没有被任何线程持有。

  • 当有线程持有锁时计数器进行自增并且记下锁的持有线程,当同一线程继续获取锁时计数器继续自增。
  • 当线程退出代码块时相应地计数器减1,直到计数器为0时锁被释放。此时该锁才能被其他线程获得。

同一线程的外层方法获得锁之后,内层方法可以直接获取改锁,可以避免内外层死锁(如下图)。


Object locker=new Object();
 
synchronized(locker){
    synchronized(locker){
 
    }
}

synchronized是可重入锁,可以防止出现死锁

当线程进入了外层的 synchronized 方法时会拿到该锁,加上锁后将会执行代码。而内部又有一个 synchronized修饰的方法,此时也需要获取到同一把锁。想要获取之前的锁就必须要让外层的方法执行完后释放锁,但外层 synchronized 包裹的代码执行完则需要内部的代码先执行完才行。因此该方法无法继续执行,产生了死锁。

此时synchronized 是可重入锁就很好的解决了死锁的问题。

二、使用

1、修饰普通方法

使用synchronized修饰普通方法时,其作用域是整个方法,锁住的对象仅仅是当前对象。

synchronized void func1(){

}

2、修饰静态方法

使用synchronized修饰静态方法时,其作用域时整个静态方法,因为静态方法属于类而不是对象,因此锁住的对象时当前类对象。

synchronized static void func2() {
        
}

3、修饰代码块

使用synchronized修饰代码块时,其作用域是整个代码块,作用对象是括号中的对象,这个作用对象可以是指定的对象,也可以是类。

Object locker=new Object();

synchronized (locker) {

}
  • 在 Java 中,任何一个继承自 Object 类的对象,都可以作为锁对象。加锁操作实际上是在操作 Object 对象头中的一个标识位。
  • 如果括号中的是this,说明锁的对象就是当前对象。
  • 如果括号中的是 xxx.class,说明锁的对象就是类对象。

三、锁机制

synchronized:

  • 既是乐观锁,也是悲观锁。
  • 既是轻量级锁,也是重量级锁。
  • 轻量级锁基于自旋实现,重量级锁基于挂起等待实现。
  • 不是读写锁。
  • 是可重入锁。
  • 是非公平锁。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
回答: synchronized是Java用于实现线程同步的关键字。它可以用于修饰方法或代码块,以确保在同一时间只有一个线程可以访问被修饰的代码。\[1\]在Javasynchronized关键字具有可重入性,这意味着一个线程可以多次获得同一个锁。例如,子类SynchronizedUsageChild继承自父类SynchronizedUsage,并重写了同步方法synchronizedMethod1。在子类的同步方法,可以调用父类的同步方法,这验证了可重入锁的特性。\[1\] 此外,synchronized还可以作用于一个类,用于实现对类的同步。在一个类的方法使用synchronized(ClassName.class)来实现对该类的同步。\[2\]另外,synchronized还可以修饰静态方法,使得该方法在多线程环境下同步执行。\[3\] 总之,synchronized关键字在Java是实现线程同步的重要工具,它可以用于修饰方法、代码块或类,以确保在多线程环境下的线程安全性。 #### 引用[.reference_title] - *1* *3* [synchronized用法详解](https://blog.csdn.net/ganmaotong/article/details/124501478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [synchronized详解](https://blog.csdn.net/m0_53474063/article/details/112389756)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值