当前位置: 首页 > article >正文

Java中的互斥锁介绍

前言

  互斥锁是一种广泛应用于多线程编程中的并发控制机制。在Java中,互斥锁有很多不同的实现方式,在本文中我们将介绍Java中常见的几种互斥锁实现方式,并讲解它们的用法、原理和代码案例。

synchronized关键字

  在Java中,采用synchronized关键字可以实现线程之间的互斥操作。具体来说,使用synchronized关键字可以保证同一时刻只有一个线程可以进入到临界区域(即加锁的代码块)执行。当一个线程访问某个对象的synchronized代码块或方法时,其他试图访问该对象的线程将会被阻塞,直到当前线程执行完这个代码块或方法并释放锁。

  synchronized关键字采用的是悲观锁机制,即在加锁的代码块或方法内部,系统默认认为其他线程会同时访问共享资源,因此需要加锁保护,以避免所谓的“脏数据”等情况。它的优点在于使用方便简单,缺点在于对于性能开销较大,而且只支持非公平锁。

  下面是synchronized关键字的一个示例代码:

public class SynchronizedDemo {
    public synchronized void synchronizedMethod() {
        // 临界区域
        // ...
    }
}

ReentrantLock类

  ReentrantLock类也是Java中的互斥锁实现方式之一,与synchronized不同的是,它提供了更加灵活的加锁和解锁机制。当一个线程获取了ReentrantLock实例的锁后,可以重复多次进入到临界区域执行,而不必像synchronized一样一次性获得或释放所有的锁。

  ReentrantLock提供了两种锁模式:公平锁和非公平锁。公平锁采用先进先出的机制,即等待时间最长的线程将获取到锁,这样可以保证所有线程在竞争资源时具有相同的机会。而非公平锁则允许线程由于优先级等因素插队获取锁,这样可能会导致某些线程长时间无法获取锁,从而造成饥饿现象。

  下面是ReentrantLock类的一个示例代码:

public class ReentrantLockDemo {
    private final ReentrantLock lock = new ReentrantLock();

    public void reentrantLockMethod() {
        lock.lock();
        try {
            // 临界区域
            // ...
        } finally {
            lock.unlock();
        }
    }
}

Semaphore类

  Semaphore是Java中另一种常见的互斥锁实现方式,它可以控制同时访问某个资源的线程数量,并允许多个线程同时访问同一个资源。Semaphore内部维护了一个计数器,用于记录当前可用的许可证数量,当线程需要获取许可证时,会调用acquire()方法进行等待,当许可证可用时,才能获取到许可证并执行相应的操作,执行完毕后需要调用release()方法释放许可证。

  Semaphore在一些场景下非常适用,例如必须限制某一资源的并发访问数量时。它也可以用来控制线程池中任务的数量,限制同时执行的任务数量。

  下面是Semaphore类的一个示例代码:

public class SemaphoreDemo {
    private final Semaphore semaphore = new Semaphore(1);

    public void semaphoreMethod() throws InterruptedException {
        try {
            semaphore.acquire();
            // 临界区域
            // ...
        } finally {
            semaphore.release();
        }
    }
}

ReadWriteLock接口

  ReadWriteLock接口是Java中提供的读写锁机制,它允许多个线程同时读取共享资源,但只允许一个线程进行写操作。ReadWriteLock接口包含两个锁对象:读锁和写锁,读锁可以被多个线程同时获取,但写锁必须独占。当有线程持有写锁时,其他线程无法获得读锁或写锁,直到该线程释放写锁。

  ReadWriteLock适用于读操作频繁而写操作较少的场景,它可以提高系统的并发读取性能并保证数据一致性。例如,在某些场景下,我们需要将一些数据从数据库缓存到内存中,这些数据在内存中是只读的,可以使用ReadWriteLock来实现,以保证数据安全和性能。

  下面是ReadWriteLock接口的一个示例代码:

public class ReadWriteLockDemo {
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private final Lock readLock = readWriteLock.readLock();
    private final Lock writeLock = readWriteLock.writeLock();
    private String data;

    public String readData() {
        readLock.lock();
        try {
            return data;
        } finally {
            readLock.unlock();
        }
    }

    public void writeData(String newData) {
        writeLock.lock();
        try {
            data = newData;
        } finally {
            writeLock.unlock();
        }
    }
}

  以上就是Java中常见的互斥锁实现方式及其用法、原理和代码案例介绍。在实际应用中,选择合适的互斥锁实现方式可以提高程序的并发性能和稳定性,需要结合具体场景进行选择和使用。


http://www.kler.cn/a/17678.html

相关文章:

  • Java NIO 深度解析:构建高效的 I/O 操作
  • ⾃动化运维利器Ansible-基础
  • 算法学习第一弹——C++基础
  • 蓝桥杯c++算法学习【2】之搜索与查找(九宫格、穿越雷区、迷宫与陷阱、扫地机器人:::非常典型的必刷例题!!!)
  • makefile 设置动态库路径参数
  • Javaweb—Ajax与jQuery请求
  • 如何挖到人生中第一个漏洞?保姆级漏洞挖掘教学
  • Docker
  • vim操作笔记
  • QT Graphics View坐标系转换
  • 一分钟快速实现Flask框架与SQLAlchemy框架的整合
  • 解释器模式
  • Unity 过场工具(Cutscene)设计(三)
  • 2023.5.7 第五十二次周报
  • B019_子查询篇
  • 从五一的旅游热潮看,该如何实现数字文旅的转型升级?
  • 浅聊一下cmake
  • 降维算法详解:理论及示例代码实现
  • 自学SQL入门(2)
  • 如何写出高质量代码
  • UG NX二次开发(C++)-用UF_OBJ_cycle_objs_in_part遍历对象
  • 顺序表的基本操作(初始化,增,删,查,改等等)
  • 【c语言】字符串匹配(搜索) | API仿真
  • Nginx快速入门
  • I.MX6Q-SDB开发板移植ubuntu
  • MySQL5.7和MySQL8.0的区别是什么