0
点赞
收藏
分享

微信扫一扫

7.Lock 同步锁

7.Lock 同步锁

Lock( 锁 )

  • 从​​JDK 5.0​​开始,​​Java​​提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用​​Lock​​对象充当。
  • ​java.util.concurrent.locks.Lock​​​接口 是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对 ​​Lock​​ 对象加锁,线程开始访问共享资源之前应先获得​​Lock​​对象。
  • ​ReentrantLock​​​ 类 是实现了 ​​Lock​​ 接口的一个实现类 ,它拥有与 ​​synchronized​​ 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是​​ReentrantLock​​类,可以显式加锁、释放锁。

显示锁 Lock

-  Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized  volatile 。Java 5.0 后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能。

- ReentrantLock 实现了 Lock 接口,并提供了与 synchronized 相同的互斥性和内存可见性。但相较于 synchronized 提供了更高的处理锁的灵活性。

Lock(锁)示例

import java.util.concurrent.locks.ReentrantLock;

class A{
private final ReentrantLock lock = new ReentrantLock(); // 创建锁

public void m(){
lock.lock();

try{
//保证线程安全的代码; }
finally{
lock.unlock();
}
}
}
// 注意:如果同步代码有异常,要将unlock()写入finally语句块

下面再写一个将前面账号取款的线程安全问题的示例。

线程安全问题的示例 - 多线程窗口卖票

1.首先创建一个售票的线程类

//创建线程类: 售卖车票
class Ticket implements Runnable {

//成员属性
private int tick = 100;

//重写run
@Override
public void run() {
//循环卖票,直到票卖完
while (true) {
//存在有票,继续售卖
if (tick > 0) {
//休眠500毫秒
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卖票
tick--;
//打印当前的票数
System.out.println(Thread.currentThread().getName() + " 剩余票:" + tick);
} else {
break;
}

}
}
}

2.创建三个线程,同时售票,演示线程安全问题

public class TestLock {
public static void main(String[] args) {
//创建线程类对象
Ticket ticket = new Ticket();
//创建三个线程
new Thread(ticket, "1号窗口").start();
new Thread(ticket, "2号窗口").start();
new Thread(ticket, "3号窗口").start();
}
}

测试执行如下:


7.Lock 同步锁_多线程

image-20201102234826929

使用 Lock 解决线程安全问题

1.在售票的线程类创建 Lock,并且设置上锁以及释放锁

7.Lock 同步锁_设计模式_02


image-20201102235725467

//创建线程类: 售卖车票
class Ticket implements Runnable {
//成员属性
private int tick = 100;
//创建 lock 锁
private final ReentrantLock lock = new ReentrantLock();
//重写run
@Override
public void run() {
//循环卖票,直到票卖完
while (true) {
lock.lock(); // 上锁
//存在有票,继续售卖
try {
if (tick > 0) {
//休眠500毫秒
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卖票
tick--;
//打印当前的票数
System.out.println(Thread.currentThread().getName() + " 剩余票:" + tick);
}
} finally {
lock.unlock(); // 在finally释放锁
}

}
}
}

2.再次测试执行如下

7.Lock 同步锁_多线程_03


image-20201102235505984

可以看到已经逐个执行了,没有出现重复值。


举报

相关推荐

0 条评论