概述
用idea debug功能演示上一篇博客中提到的
本实现中的出队、入队的实现逻辑会不会有线程安全问题?如果有,怎么解决?
测试用例
package com.lovehena.datastructure.test;import com.lovehena.datastructure.ArrayQueue;/*
* 测试 offer() poll()方法的线程安全问题
* */
public class TestArrayQueue2 {/*** 测试 offer() 方法的线程安全问题* @param args*/public static void main(String[] args) throws InterruptedException {ArrayQueue queue = new ArrayQueue(3);/*** 预期是 线程1将1入队 线程2将2入队* 但由于可能发生指令交错 导致线程安全问题 则可能的结果是 队列中只有2 或者 只有1* 用idea debug功能模拟*/Thread t1 = new Thread(() -> {queue.offer(1);}, "t1");Thread t2 = new Thread(() -> {queue.offer(2);}, "t2");t1.start();t2.start();// 等待t1、t2线程执行完毕t1.join();t2.join();// 打印得到的queuequeue.print();}
}
演示
文字不好叙述,录制了一个视频。
测试用例输出
元素2将元素1覆盖的情形
元素1将元素2覆盖的情形
解决线程安全问题
常见思路就是加锁。
我这个不涉及集群部署,所以用synchronized、lock(java.util.concurrent.locks.Lock)实现即可。
代码示例
// 多个线程往同一队列中入队元素时,确保锁是同一个。// 一般将锁对象设置为队列的一个成员变量private ReentrantLock lock=new ReentrantLock(); // 控制offer的锁
public boolean offer(int value) {lock.lock(); // 加锁成功后 以下代码才会被执行try {if (tail == capacity) { //队列放满了log.info("元素 {} 入队失败 因为队列放满了", value);return false;}arr[tail] = value;tail++;}finally {lock.unlock(); // 一定要记得手动释放锁 否则导致其他线程无法获取到锁 进而无法入队元素}return true;}
以上代码经测试,不会再有线程安全问题。
扩展
测试poll()方法的线程安全问题。
加锁解决poll()方法的线程安全问题。
最后
好了,如果对你有帮助的话,欢迎点个免费的赞哦。