【Java】synchronized、ReentrantLock 两种锁区分

简介: 【Java】synchronized、ReentrantLock 两种锁区分

1.synchronized

在 JDK 1.6 之前,synchronized 是重量级锁,效率低下。

从 JDK 1.6 开始,synchronized 做了很多优化,如偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销。

synchronized同步锁的四种状态:无锁、偏向锁、轻量级锁、重量级锁。根据实际情况进行相应锁升级,但是锁不可以降级

特性

1. **对象锁** :使用 synchronized 修饰非静态的方法以及 synchronized(this) 同步代码块使用的锁是对象锁。
2. **类锁** :使用 synchronized 修饰静态的方法以及 synchronized(类名.class) 同步代码块使用的锁是类锁
3. **私有锁** :在类内部声明一个私有属性如private Object lock,在需要加锁的同步块使用 synchronized(lock)

特点

  • 对象锁具有 可重入性 (即可以重复 递归调用 ,而 不会死锁 )。
  • 当一个线程获得了某个对象的对象锁,则该线程仍然可以调用其他任何需要该对象锁的 synchronized 方法或 synchronized(this) 同步代码块(其实也是 可重入性 的一种表达)。
  • 当一个线程访问某个对象的一个 synchronized(this) 同步代码块时,其他线程对该对象中所有其它 synchronized(this) 同步代码块的访问将被阻塞,因为访问的是同一个对象锁()。
  • 每个类 只有一个类锁 ,但是类可以实例化成对象,因此每一个对象对应一个对象锁。
  • 类锁和对象锁不会产生竞争。
  • 私有锁和对象锁也不会产生竞争。
  • 使用私有锁可以减小锁的 细粒度 ,减少由锁产生的开销。

实例

package com.company;

import java.util.ArrayList;
import java.util.List;

public class Main {

    private Object o=new Object();
    synchronized void method1(){
        //对象锁(锁非静态方法)
    }
    void method2(){
        synchronized (this){
            //对象锁
        }
        synchronized (o){
            //私有锁
        }
        synchronized (Main.class){
            //类锁
        }
    }
    static synchronized void method3(){
        //类锁
    }
}

2.ReentrantLock

相对于 synchronized,它更加灵活。但是需要自己写出加锁和解锁的过程。它的灵活性在于它拥有很多特性,ReentrantLock
需要显示地进行释放锁。特别是在程序异常时,synchronized 会自动释放锁,而 ReentrantLock 并不会自动释放锁,所以 必须在
finally 中进行释放锁

特性:

  • 公平性:支持公平锁和非公平锁。默认使用了非公平锁。

  • 可重入:指一个线程在持有锁的情况下,能够再次获取同一个锁,而不会被自己所持有的锁所阻塞。

  • 可中断:相对于 synchronized,它是可中断的锁,能够对中断作出响应。

  • 超时机制:超时后不能获得锁,因此不会造成死锁。

package com.company;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    Lock lock = new ReentrantLock();
    public static void main(String[] args) {


    }
    void method(){
        try {
            lock.lock();
            System.out.println("Hello");
        }finally {
            //最后一定要再finally中释放锁
            lock.unlock();
        }

    }

}

有关知识链接:Java 各种锁的小结 - 知乎

目录
相关文章
|
28天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
39 2
|
7天前
|
Java
Java 中锁的主要类型
【10月更文挑战第10天】
|
9天前
|
算法 Java 程序员
Java中的Synchronized,你了解多少?
Java中的Synchronized,你了解多少?
|
8天前
|
Java
让星星⭐月亮告诉你,Java synchronized(*.class) synchronized 方法 synchronized(this)分析
本文通过Java代码示例,介绍了`synchronized`关键字在类和实例方法上的使用。总结了三种情况:1) 类级别的锁,多个实例对象在同一时刻只能有一个获取锁;2) 实例方法级别的锁,多个实例对象可以同时执行;3) 同一实例对象的多个线程,同一时刻只能有一个线程执行同步方法。
9 1
|
11天前
|
Java 开发者
在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选
【10月更文挑战第6天】在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选。相比 `synchronized`,Lock 提供了更灵活强大的线程同步机制,包括可中断等待、超时等待、重入锁及读写锁等高级特性,极大提升了多线程应用的性能和可靠性。通过示例对比,可以看出 Lock 接口通过 `lock()` 和 `unlock()` 明确管理锁的获取和释放,避免死锁风险,并支持公平锁选择和条件变量,使其在高并发场景下更具优势。掌握 Lock 接口将助力开发者构建更高效、可靠的多线程应用。
18 2
|
7天前
|
安全 Java 开发者
java的synchronized有几种加锁方式
Java的 `synchronized`通过上述三种加锁方式,为开发者提供了从粗粒度到细粒度的并发控制能力,满足了不同场景下的线程安全需求。合理选择加锁方式对于提升程序的并发性能和正确性至关重要,开发者应根据实际应用场景的特性和性能要求来决定使用哪种加锁策略。
9 0
|
8天前
|
Java 应用服务中间件 测试技术
Java21虚拟线程:我的锁去哪儿了?
【10月更文挑战第8天】
19 0
|
Java
java源码 - ReentrantLock之FairSync
开篇  这篇文章主要是讲解FairSync公平锁的源码分析,整个内容分为加锁过程、解锁过程,CLH队列等概念。  首先一直困扰我的CLH队列的CLH的缩写我终于明白,看似三个人的人名的首字符缩写"CLH" (Craig, Landin, andHagersten)。
1027 0
|
Java
java源码 - ReentrantLock之NonfairSync
开篇  NonfairSync和FairSync相比而言,多了一次抢占机会,其他处理逻辑几乎是一模一样。 NonfairSync的tryAcquire的操作流程中如果发现当前锁未被占用那么立即抢占锁。
1075 0
|
4天前
|
安全 Java UED
Java中的多线程编程:从基础到实践
本文深入探讨了Java中的多线程编程,包括线程的创建、生命周期管理以及同步机制。通过实例展示了如何使用Thread类和Runnable接口来创建线程,讨论了线程安全问题及解决策略,如使用synchronized关键字和ReentrantLock类。文章还涵盖了线程间通信的方式,包括wait()、notify()和notifyAll()方法,以及如何避免死锁。此外,还介绍了高级并发工具如CountDownLatch和CyclicBarrier的使用方法。通过综合运用这些技术,可以有效提高多线程程序的性能和可靠性。