我有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;
}
}
答案 0 :(得分:3)
根本不是线程安全的。
您只需将synchronized
关键字添加到4种方法的声明中即可。你很幸运,这样一个简单的解决方案适用于你的班级,因为并非总是如此。
一个可能棘手的问题是String[]
返回的getData
。你在每次调用时都创建了一个新数组,所以你没有遇到任何问题,但如果它返回了对内部数组的一些引用,那么同步它会很复杂。
答案 1 :(得分:0)
不,它不是线程安全的。
如果从2个不同的线程调用getData()
和addData()
,那么您100%肯定会遇到麻烦,主要是因为两个线程都会访问bufferSize
;一个叫getData()
,另一个叫addData()
。
要解决此问题,您应该在修改bufferSize
成员变量之前先获取锁定。
This应该可以帮助您开始使用线程和锁以及如何保护共享资源。
答案 2 :(得分:0)
为此,您使用信号量,因为您使用的是基本数组。 Arraylists可以用作线程安全的方法。但是在您的实现中,您希望在每个使用缓冲区调用semaphore.aquire()的方法中创建信号量,并在完成后调用semaphore.release()