Java锁Synchronized不同用法的区别

本文深入探讨了Java中Synchronized锁的用法及其对线程安全的保障作用。包括锁的原子性和可见性特性,以及如何通过对象锁和类锁实现多线程环境下的资源同步。同时,详细解析了锁在不同场景下的应用,如方法级锁和代码块级锁,并讨论了锁的互斥性。

一、Synchronized锁用法示例:

synchronized用处是什么?
synchronized保证了线程的原子性。(一个线程在执行被保护的代码块时,没有任何线程会同时访问)
synchronized还保证了可见性。(当执行完synchronized之后,修改后的变量对其他的线程是可见的)
Java中的synchronized,通过使用内置锁,来实现对变量的同步操作,进而实现了对变量操作的原子性和其他线程对变量的可见性,从而确保了并发情况下的线程安全。

1)加在方法上:

非静态方法:public synchronized void test(){...}
静态方法: public static synchronized void test2(){...}

2)加在代码锁

类锁

public void test(){
    ...
    synchronized (ObjLockTest.class){
        ...
    }
    ...
}

对象锁

public void test2(){
    ...
    synchronized (this){
        ...
    }
    ...
}

对象所

public void test3(){
    ...

   A a = new A();
    synchronized (a){
        ...
    }
    ...
}

二、Synchronized锁从被拥有者角度而言,分为对象锁与类锁;

1)Synchronized修饰非静态方法,或非静态方法中的代码块,或指定对象时,锁为对象锁;对象锁是属于当前对象的;

2)Synchronized修饰静态方法,或静态方法中的代码块,或指定对象为XXX.class时,锁为类锁;类锁是属于class的,是这个类的所有对象及class共用的一把锁;

 

一个对象只有一把对象锁及一把类锁:

1)多个线程都需要同一对象的对象锁时(注:可能是调用同一个方法,也可能是调用不同的方法来获取锁),只有一个线程能拿到锁,其他线程都需等待;

2)多个线程都需要多个对象的类锁时(注:可能是调用同一个方法,也可能是调用不同的方法来获取锁),只有一个线程能拿到锁,其他线程都需等待;

3)而2个线程,一个需要对象锁,一个需要类锁时,即使同时发生也不会相互影响(注:此结论本人通过代码测试证明是2个锁,不互斥的);

 

### Java 中 `synchronized` 关键字的使用场景与原理 #### 一、`synchronized` 的作用 `synchronized` 是 Java 提供的一种内置机制,用于控制多线程环境下对共享资源的竞争访问。通过加的方式,它可以确保同一时刻只有一个线程可以执行被保护的代码区域,从而保障数据的一致性和完整性[^1]。 --- #### 二、`synchronized` 的使用方式 `synchronized` 支持两种主要的使用形式: 1. **同步方法** 当将 `synchronized` 应用于实例方法时,该方法会自动获取当前对象的对象级(即 `this`)。其他线程如果尝试调用同一个对象上的任何 `synchronized` 方法,则会被阻塞直到释放。 ```java public class Counter { private int count; // 同步方法 public synchronized void increment() { count++; } } ``` 这种方式适用于整个方法都需要保持原子性的场景[^1]。 2. **同步代码块** 如果只需要对部分代码进行同步操作,可以通过 `synchronized` 块指定一个特定的对象作为来减少定范围。这种方式更加灵活且高效。 ```java public class SharedResource { private final Object lock = new Object(); private int value; public void updateValue(int newValue) { synchronized (lock) { // 明确指定了对象 this.value = newValue; } } } ``` 此外,在静态方法中也可以应用 `synchronized`,此时使用的是类级别的(即 `Class` 对象),而不是某个具体实例的[^2]。 --- #### 三、`synchronized` 的底层实现 在 JVM 层面,`synchronized` 的实现依赖于 Monitor 和其内部的数据结构——ObjectMonitor。当线程进入由 `synchronized` 守护的临界区时,JVM 需要完成以下几个动作: - 获取目标对象的监视器(Monitor)。 - 将线程加入等待队列并测试是否有可用的。 - 成功获得后允许继续运行;否则挂起直至条件满足。 为了提高性能表现,现代 JDK 实现了多种优化策略,其中包括但不限于轻量级、偏向以及重量级之间的动态转换过程,这一系列技术统称为 *升级* 或者说是自适应膨胀机制[^2]。 --- #### 四、的状态变迁(升级) 初始状态下,默认采用的是无竞争模式下的最简单形态—**偏向**。一旦检测到有多个线程频繁争夺相同资源,则逐步提升至更高级别的状态以应对复杂情况: 1. **偏向**: 初始默认设置,假设只存在单一线程持续持有某把的情况,因此无需实际争抢即可快速复用已有权限; 2. **轻量级**: 若发现不同线程交替请求同一件事物,则切换至此阶段利用 CAS 操作代替传统互斥算法降低开销; 3. **重量级**: 在极端条件下发生激烈冲突时退化成操作系统层面的传统信号量处理手段。 这种分层设计有效平衡了效率与公平性之间矛盾关系的同时也极大提升了程序整体吞吐能力。 --- ### 总结 综上所述,`synchronized` 不仅提供了便捷易懂的方法帮助开发者构建安全可靠的并发应用程序,而且经过多次迭代改进之后已经成为一种既强大又高效的解决方案之一。无论是初学者还是资深工程师都应该熟练掌握它的基本概念及相关技巧以便更好地解决现实世界中的各种挑战。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值