为了账号安全,请及时绑定邮箱和手机立即绑定

{求解答}一个有关互斥锁的问题

{求解答}一个有关互斥锁的问题

MM们 2019-02-20 10:29:32
我想要实现这么一个功能:程序中有一个数组0~15,一共16个帧序号用来标识下发的报文。报文下发时,需要给它一个帧序号;如果下发的报文被客户端接收并返回,需要重新回收该报文的帧序号。为了避免在给多个报文分配帧序号时出现重复帧序号的情况,我在分配帧序号的方法里用了个互斥锁,锁住了一个用来管理闲置的帧序号的变量,但同时,这又出现了另外一个问题,下面我放上代码,问题写在OfferFrameNo()里的注释上: public class FrameNumberController { private static int MAX_FRAME_NO = 16; static Map<Integer,byte[]> frame_info = new HashMap<Integer, byte[]>();//存储还在处理的frame的信息 static List<Integer> available_no = new ArrayList<Integer>();//闲置的帧序号 static void init(){ for (int i = 0; i < MAX_FRAME_NO; i++){ available_no.add(i); } } public static void RecordFrame(int frame_no, byte[] output){ frame_info.put(frame_no, output); } public static void RecallFrameNo(int frame_no){ frame_info.remove(frame_no); available_no.add(frame_no); } public static int OfferFrameNo(){ int frame_no = 0; int available_no_size=0; /* * 避免同时获取同一个frame_no * 添加互斥锁 */ //******互斥锁开始***** synchronized(available_no){ /*Q:有问题,如果available_no已经没有可用号码了,当RecallFrameNo要召回frame_no, 但是因为这里的互斥锁而没有召回成功的话,就会变成死循环了,肿么办?*/ while(available_no_size <= 0){ available_no_size = available_no.size(); } frame_no = available_no.get(0); available_no.remove(0); } //******互斥锁结束***** return frame_no; } } 我有想过把判断是否有闲置帧序号的循环放到互斥锁外面,像这样: while(available_no_size <= 0){ available_no_size = available_no.size(); } synchronized(available_no){ frame_no = available_no.get(0); available_no.remove(0); } 但又可能出现另一个问题。万一,某个线程在进入互斥锁的前一瞬间available_no_size不等于0,后一瞬间就被另外一个线程获取了这个唯一闲置的帧序号呢?这种情况会不会有可能发生?第一次用互斥锁,可能也没有搞清楚它的用法,请各位提供一下思路,谢谢。 ————————————EDIT————————————又或者把available_no_size也加一个互斥锁?这样会不会显着很累赘? synchronized(available_no_size){ while(available_no_size <= 0){ available_no_size = available_no.size(); } } synchronized(available_no){ frame_no = available_no.get(0); available_no.remove(0); }
查看完整描述

2 回答

?
守着星空守着你

TA贡献1799条经验 获得超8个赞

java.util.concurrent.LinkedBlockingQueue 楼主可以直接使用这个队列,是线程安全的。

queue.take() 获取数据,如果当前没有数据,则阻塞直到返回可用数据
queue.poll() 获取数据,如果当前没有数据,返回null
queue.pool(timeout, TimeUnit) 获取数据,如果没有数据,阻塞一定的时间后如果有数据直接返回,没有则返回null

public class FrameNumberController {
    private static int MAX_FRAME_NO = 16;
    static Map<Integer, byte[]> frame_info = new HashMap<Integer, byte[]>();//存储还在处理的frame的信息
    static LinkedBlockingQueue<Integer> available_no = new LinkedBlockingQueue<>();//闲置的帧序号

    static void init() {
        for (int i = 0; i < MAX_FRAME_NO; i++) {
            available_no.add(i);
        }
    }

    public static void RecordFrame(int frame_no, byte[] output) {
        frame_info.put(frame_no, output);
    }

    public static void RecallFrameNo(int frame_no) {
        frame_info.remove(frame_no);
        available_no.add(frame_no);
    }

    public static int OfferFrameNo() {
        try {
            return available_no.take();
        } catch (InterruptedException e) {
            // 处理错误
            throw new RuntimeException(e);
        }
    }
}
查看完整回答
反对 回复 2019-03-01
?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

使用BlockingQueue呀,简单易懂

查看完整回答
反对 回复 2019-03-01
  • 2 回答
  • 0 关注
  • 449 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信