线程安全循环缓冲区?

时间:2011-12-07 20:36:57

标签: java thread-safety

我有2个线程,一个插入数据,第二个线程检索数据 我得到了非常奇怪的结果。

线程是否安全?

如果没有,如何解决?

这是我的循环缓冲区:

private int mBufferSize;
    private int startPointer = 0;
    private int endPointer = 0;
    private int bufferSize = 0;
    private String[] buffer;

    public BBuffer(int size) {
        mBufferSize = size;
        startPointer = 0;
        endPointer = 0;
        bufferSize = 0;
        buffer = new String[mBufferSize];
    }


    public String[] getData() {
        String data = null;

        if (!isEmpty()) {
            bufferSize--;
            startPointer = (startPointer + 1) % mBufferSize;
            data = (String) buffer[startPointer];


        } else {

            System.err.println("!");
            return null;
        }

        return data.split(",");
    }

    public  void addData(String data) {
        if (!isFull()) {
            bufferSize++;
            endPointer = (endPointer + 1) % mBufferSize;
            buffer[endPointer] = data;
            System.out.println("->"+data);
        } else {
            System.out.println("full");
        }
    }

    public boolean isEmpty() {
        return bufferSize == 0;
    }

    public boolean isFull() {
        return bufferSize == mBufferSize;
    }

}

3 个答案:

答案 0 :(得分:3)

根本不是线程安全的。

您只需将synchronized关键字添加到4种方法的声明中即可。你很幸运,这样一个简单的解决方案适用于你的班级,因为并非总是如此。

一个可能棘手的问题是String[]返回的getData。你在每次调用时都创建了一个新数组,所以你没有遇到任何问题,但如果它返回了对内部数组的一些引用,那么同步它会很复杂。

答案 1 :(得分:0)

不,它不是线程安全的。 如果从2个不同的线程调用getData()addData(),那么您100%肯定会遇到麻烦,主要是因为两个线程都会访问bufferSize;一个叫getData(),另一个叫addData()。 要解决此问题,您应该在修改bufferSize成员变量之前先获取锁定。 This应该可以帮助您开始使用线程和锁以及如何保护共享资源。

答案 2 :(得分:0)

为此,您使用信号量,因为您使用的是基本数组。 Arraylists可以用作线程安全的方法。但是在您的实现中,您希望在每个使用缓冲区调用semaphore.aquire()的方法中创建信号量,并在完成后调用semaphore.release()