java多线程互斥锁_浅谈Java多线程互斥锁

本文介绍如何使用Java中的ReentrantLock和synchronized关键字解决多线程环境下资源的竞争问题,确保同一时刻只有一个线程能访问共享资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了解决竞争条件带来的问题,我们可以对资源上锁。多个线程共同读写的资源称为共享资源,也叫临界资源。涉及操作临界资源的代码区域称为临界区(Critical Section)。同一时刻,只能有一个线程进入临界区。我们把这种情况称为互斥,即不允许多个线程同时对共享资源进行操作,在同一时间只能被一个线程所占有的锁称之为Java多线程互斥锁。

互斥锁在java中的实现就是 ReetranLock , 在访问一个同步资源时,它的对象需要通过方法 tryLock() 获得这个锁,如果失败,返回 false,成功返回true。根据返回的信息来判断是否要访问这个被同步的资源。ReentrantLock 互斥锁是可重入锁,即某一线程可多次获得该锁。

进入临界区前,需要先获得互斥锁。如果已经有线程正在使用资源,那么需要一直等待,直到其它线程归还互斥锁。

操作完共享资源之后,即退出临界区时,需要归还互斥锁,以便其它等待使用该资源的线程能够进入临界区。

伪代码示例:

wait(lock); //获得互斥锁

{

临界区,操作共享资源

}

signal(lock); //归还互斥锁

Java 中可以使用 ReentrantLock 对临界区上锁,防止多个线程同时进入临界区:

private static Lock bufferLock = new ReentrantLock();

public static void print(String msg) {

bufferLock.lock();

//临界区,操作临界资源 globalBuffer

bufferLock.unlock();

}

这里我们只需要在临界区前使用 lock() 上锁,在临界区后使用 unlock() 解锁即可,java.util.concurrent 帮我们实现了临界区前判断锁状态的工作,会自己决定是阻塞还是进入临界区。

synchronized 关键字

java 为我们提供了更加简便的方式,用于实现临界区的互斥。

例如,我们可以为操作共享资源的函数加上 synchronized 关键字:

public synchronized void myFunction() {

//操作共享资源 A

}

通过这种方式,能够确保同一时刻最多只有一个线程在执行该函数。如果资源 A 只在该函数中读写,那么可以保证资源 A 不会出现被多个线程同时读写的情况。

但是,如果在其它函数中也对共享资源 A 进行操作,那么就不能使用这种方式来实现资源的使用互斥。因为即使这些函数都声明为 synchronized,也只是说明同一时刻不能有多个线程执行同一个函数,但允许多个线程同时执行不同的函数,而这些函数都在操作同一个资源 A。

下面我们给出另一种方法来实现资源使用的互斥锁。

synchronized 代码块

通过声明函数为 synchronized 的方式,只能实现函数体的互斥。要确保资源使用的互斥,即同一时刻只能有一个线程使用该资源,可以将操作资源 A 的语句放入 synchronized 代码块:

public void function1() {

......

synchronized (A) {

//操作资源 A

}

......

}

public void function2() {

......

synchronized (A) {

//操作资源 A

}

......

}

这样,对于资源 A 来说,同一时刻,只能有一个对应的 synchronized 代码块执行。因此,无论是在哪个地方使用资源 A,都不会出现多个线程竞争该资源的情况。

由ReentrantLock 的构造函数可见,在实例化 ReentrantLock 的时候我们可以选择实例化一个公平锁或非公平锁,而默认会构造一个非公平锁。公平锁与非公平锁区别在于竞争锁时的有序与否。Java多线程互斥锁ReentrantLock是通过继承接口Lock而实现的,类似的还有继承 ReadWriteLock 实现的 ReentrantReadWriteLock(读写锁),对此,在本站的Java多线程教程中有进一步的讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值