Java 中的Lock锁
Lock锁,可以得到和synchronized一样的效果,即实现原子性、有序性和可见性。相较于synchronized,Lock锁可手动获取锁和释放锁、可中断的获取锁、超时获取锁。Lock是一个接口,两个直接实现类:ReentrantLock(重入锁), ReentrantReadWriteLock(读写锁)。1.概述Lock锁,使用时手动获取锁和释放锁,比synchro...
Lock锁,可以得到和 synchronized一样的效果,即实现原子性、有序性和可见性。
相较于synchronized,Lock锁可手动获取锁和释放锁、可中断的获取锁、超时获取锁。
Lock 是一个接口,两个直接实现类:ReentrantLock(重入锁), ReentrantReadWriteLock(读写锁)。
1. 概述
Lock锁,使用时手动获取锁和释放锁,比synchronized更加灵活;可中断的获取锁;超时获取锁。
Lock 锁的基本用法, l.lock()方法进行上锁, l.unlock()方法进行解锁,如下所示。
Lock l = ...;
l.lock(); // 上锁
try {
// access the resource protected by this lock
} finally {
l.unlock(); // 解锁
}
2. Lock锁的API
修饰符和类型 | 方法 | 描述 |
void | lock() | 获得锁。 |
void | lockInterruptibly() | 获得锁,可中断。举个例子,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。 |
boolean | tryLock() | 锁在空闲的才能获取锁(未获得锁不会等待)。举个例子:当两个线程同时通过lock.trylock()想获取某个锁时,假若此时线程A获取到了锁,而线程B不会等待,直接放弃获取锁。 |
boolean | tryLock(long time, TimeUnit unit) | 如果锁定可用,则此方法立即返回值 如果锁不可用,则当前线程将被禁用以进行线程调度,并且在发生以下三种情况之一之前处于休眠状态:
|
void | unlock() | 释放锁。 |
3. lock() 方法,unlock()方法
创建一个 Lock 锁:
Lock l = new ReentrantLock();
给代码块上锁:
l.lock();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": ");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
l.unlock();
全部代码:
package lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyLockStudy implements Runnable {
private int count;
Lock l = new ReentrantLock();
@Override
public void run() {
l.lock();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": ");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
l.unlock();
}
public static void main(String args[]) {
MyLockStudy runn = new MyLockStudy();
Thread thread1 = new Thread(runn, "thread1");
Thread thread2 = new Thread(runn, "thread2");
Thread thread3 = new Thread(runn, "thread3");
thread1.start();
thread2.start();
thread3.start();
}
}
运行截图:
4. tryLock()方法
tryLock(),锁在空闲的才能获取锁(未获得锁不会等待,lock()未获得锁会进入阻塞状态 ),返回值为boolean类型,获取锁则为 true ,反之为 false。
tryLock() 进行加锁:
if (l.tryLock()) {
System.out.println(Thread.currentThread().getName() + "获取锁");
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": ");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
l.unlock();
} else {
System.out.println(Thread.currentThread().getName() + "未获取锁");
}
完整代码:
package lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyLockStudy implements Runnable {
private int count;
Lock l = new ReentrantLock();
@Override
public void run() {
if (l.tryLock()) {
System.out.println(Thread.currentThread().getName() + "获取锁");
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": ");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
l.unlock();
} else {
System.out.println(Thread.currentThread().getName() + "未获取锁");
}
}
public static void main(String args[]) {
MyLockStudy runn = new MyLockStudy();
Thread thread1 = new Thread(runn, "thread1");
Thread thread2 = new Thread(runn, "thread2");
Thread thread3 = new Thread(runn, "thread3");
thread1.start();
thread2.start();
thread3.start();
}
}
运行截图如下所示:
5. tryLock(long time, TimeUnit unit) 方法
如果锁定可用,则此方法立即返回值true
。如果锁不可用,则当前线程将被禁用以进行线程调度,并且在发生以下三种情况之一之前处于休眠状态:
- 当前线程获取锁。
- 其他一些线程中断当前线程。
- 等待时间过去了,返回false
设置等待时间为 1000 毫秒。
try {
if (l.tryLock(1000, TimeUnit.MILLISECONDS)) {
System.out.println(Thread.currentThread().getName() + "获取锁");
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": ");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
l.unlock();
} else {
System.out.println(Thread.currentThread().getName() + "未获取锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
完整代码如下所示:
package lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyLockStudy implements Runnable {
private int count;
Lock l = new ReentrantLock();
@Override
public void run() {
try {
if (l.tryLock(1000, TimeUnit.MILLISECONDS)) {
System.out.println(Thread.currentThread().getName() + "获取锁");
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": ");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
l.unlock();
} else {
System.out.println(Thread.currentThread().getName() + "未获取锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
MyLockStudy runn = new MyLockStudy();
Thread thread1 = new Thread(runn, "thread1");
Thread thread2 = new Thread(runn, "thread2");
Thread thread3 = new Thread(runn, "thread3");
thread1.start();
thread2.start();
thread3.start();
}
}
运行截图:
如果锁不可用,则当前线程将被禁用以进行线程调度,并且在发生以下三种情况之一之前处于休眠状态,当前线程是可以被中断的。
package lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyLockStudy implements Runnable {
private int count;
Lock l = new ReentrantLock();
@Override
public void run() {
try {
if (l.tryLock(1000, TimeUnit.MILLISECONDS)) {
System.out.println(Thread.currentThread().getName() + "获取锁");
for (int i = 0; i <= 500000000; i++) {
if (i == 500000000) {
System.out.println("运算结束");
}
}
l.unlock();
} else {
System.out.println(Thread.currentThread().getName() + "未获取锁");
}
} catch (InterruptedException e) {
System.out.println("中断");
e.printStackTrace();
}
}
public static void main(String args[]) {
MyLockStudy runn = new MyLockStudy();
Thread thread1 = new Thread(runn, "thread1");
Thread thread2 = new Thread(runn, "thread2");
Thread thread3 = new Thread(runn, "thread3");
thread1.start();
thread2.start();
thread3.start();
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
thread2.interrupt();
thread3.interrupt();
}
}
线程1获取了锁,其他线程休眠,然后被中断。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)