Java多线程中Lock锁的使用总结

Java多线程中Lock锁的使用总结

什么是Lock?

在Java中,Lock是一种比synchronized更加灵活、功能更加强大的线程同步机制。它可以提供比传统的synchronized更为广泛的锁定操作。

Lock和synchronized的对比

  1. 锁的获取方式

synchronized是隐式获取锁,只要进入synchronized保护的代码段,锁就会自动获得,退出代码段时锁会自动释放。

而在使用Lock时,需要在代码中显式地获得和释放锁,如果没有正确释放锁,就可能导致死锁等问题。

  1. 粒度

使用synchronized时,锁粒度相对较粗,只能在代码块或者方法上进行同步,无法对其中的代码片段进行细粒度的控制。

而使用Lock时可以对某个资源进行单独的加锁和解锁,这就可以避免对整个代码块进行锁定,提高多线程执行的效率。

  1. 等待可中断

在synchronized中,如果等待获取锁的线程一直没有获取到锁,就只能一直等待下去。

而在Lock中,获取锁的操作可以设置等待时间,如果等待时间超过一定的范围仍然没有获取到锁,就可以中断等待,防止死锁的发生。

  1. 公平锁

synchronized是一种非公平锁,锁获取的顺序由系统随机决定,无法保证等待时间最长的线程一定会先获取锁。

而Lock可以通过构造方法设置是否为公平锁,公平锁保证等待时间最长的线程先获取锁,避免了某些线程长时间得不到锁的问题。

Lock的使用示例

示例一:非公平锁

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

public class LockTest {
    private Lock lock = new ReentrantLock(false);
    // false 表示这是一个不公平锁,默认为 false

    public void print() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " get lock");
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        final LockTest lockTest = new LockTest();
        Runnable runnable = () -> {
            System.out.println(Thread.currentThread().getName() + " start");
            lockTest.print();
        };
        new Thread(runnable, "thread1").start();
        new Thread(runnable, "thread2").start();
    }
}

输出结果如下:

thread1 start
thread2 start
thread1 get lock
thread2 get lock

可以看到,在不公平锁的情况下,获得锁的线程是随机的。

示例二:可重入锁

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

public class LockTest {
    private Lock lock = new ReentrantLock();

    public void print() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " get outer lock");
            Thread.sleep(1000);

            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " get inner lock");
            } finally {
                lock.unlock();
            }

            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println(Thread.currentThread().getName() + " unlock outer lock");
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        final LockTest lockTest = new LockTest();
        Runnable runnable = () -> {
            System.out.println(Thread.currentThread().getName() + " start");
            lockTest.print();
        };
        new Thread(runnable, "thread1").start();
        new Thread(runnable, "thread2").start();
    }
}

输出结果如下:

thread1 start
thread2 start
thread1 get outer lock
thread1 get inner lock
thread1 unlock outer lock
thread2 get outer lock
thread2 get inner lock
thread2 unlock outer lock

在可重入锁的情况下,同一个线程在获得锁后,可以再次获得该锁而不会被阻塞。在上面的示例中,线程1先获得了锁,在获得锁之后,又顺利地获得了一次该锁,因为是同一个线程,所以不会被阻塞。而线程2在获取锁之后也可以顺利地获取第二次锁。这个叫做可重入锁也叫做递归锁。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程中Lock锁的使用总结 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • 浅谈Nginx10m+高并发内核优化详解

    浅谈Nginx10m+高并发内核优化详解 Nginx 10m+高并发场景分析 Nginx是一个高性能、高并发的Web服务器,广泛应用于互联网企业和大型网站等高并发场景。在高并发的场景下,Nginx的性能极为重要,如何优化Nginx的性能成为了Web开发人员必须掌握的技能。下面我们就来分析一下Nginx在10m+高并发场景下的性能瓶颈和优化方案。 性能瓶颈分析…

    多线程 2023年5月16日
    00
  • 利用redis实现分布式锁,快速解决高并发时的线程安全问题

    利用Redis实现分布式锁是一种常见的解决高并发时线程安全问题的方式。在使用Redis实现分布式锁之前,需要针对具体需求选择使用哪种方式。 一、获取分布式锁的Demo 准备Redis连接客户端:我们可以使用Jedis或Lettuce等第三方开源Redis客户端,将其引入到项目中。 连接Redis服务:使用该客户端连接我们的Redis服务,用于后续的操作。 J…

    多线程 2023年5月16日
    00
  • Java多线程之线程安全问题详解

    接下来我将为大家详细讲解Java多线程之线程安全问题的完整攻略。 Java多线程之线程安全问题详解 1. 前言 在多线程编程中,线程安全问题一直备受关注。线程安全问题产生的原因有很多,比如竞态条件、共享资源、不可变对象等。本篇文章将介绍线程安全的基本概念、线程安全实现方式及其优缺点,并举例说明。 2. 线程安全基本概念 线程安全是指在多线程环境下,每个线程通…

    多线程 2023年5月17日
    00
  • Go语言开发保证并发安全实例详解

    Go语言开发保证并发安全实例详解 什么是Go语言的并发? 并发是指系统中有两个或两个以上的执行线程或执行过程。Go语言中并发可以通过goroutine和channel来实现。 goroutine goroutine是Go语言中轻量级的线程实现,可以快速高效地在程序中创建大量的并发执行的任务,而不会占用过多的CPU和内存资源。可以通过go关键字将一个函数调用变…

    多线程 2023年5月17日
    00
  • Java并发编程示例(五):线程休眠与恢复

    Java并发编程示例(五):线程休眠与恢复是介绍Java多线程中线程休眠和恢复的教程。以下是完整攻略。 线程休眠与恢复 在Java多线程中,线程的休眠和恢复是两个比较重要的概念。休眠是暂停线程的执行,一定时间后再恢复执行;而恢复就是让线程继续执行。 Java提供了Thread.sleep()方法来实现线程的休眠,其中参数单位是毫秒。当线程处于休眠状态时,它不…

    多线程 2023年5月17日
    00
  • IIS Web服务器支持高并发设置方法详解

    IIS Web服务器支持高并发设置方法详解 在应对高并发场景下,IIS Web服务器的配置是至关重要的。本文将介绍如何通过设置来提高IIS的并发处理能力。 1. 修改IIS属性设置 第一步是修改IIS属性设置,以提高服务器并发处理能力。可以按以下步骤操作: 在控制面板中找到“管理工具”,然后点击“Internet 信息服务(IIS)管理器”进入IIS配置界面…

    多线程 2023年5月16日
    00
  • Java并发编程之JUC并发核心AQS同步队列原理剖析

    针对“Java并发编程之JUC并发核心AQS同步队列原理剖析”的完整攻略,下面我将为您进行详细讲解,内容包含以下几个方面: JUC并发核心AQS AQS(AbstractQueuedSynchronizer)是JUC(JDK中对Java并发编程提供支持的工具包)并发编程的核心组件。AQS是一个用于构建锁和同步器的框架,利用AQS能够简单地构造出无锁、可重入、…

    多线程 2023年5月16日
    00
  • 详解Java多线程编程中CountDownLatch阻塞线程的方法

    详解Java多线程编程中CountDownLatch阻塞线程的方法 什么是CountDownLatch? CountDownLatch 是一个 Java 工具类,用于管理和解决多线程编程中线程等待的问题,它可以让一个或多个线程等待其他线程执行完毕后再继续执行。 CountDownLatch的原理 CountDownLatch 中心思想是等待一个或者多个线程完…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部