Java 线程安全循环缓冲区?
我有两个线程,一个线程插入数据,第二个线程检索数据。Java 线程安全循环缓冲区?,java,thread-safety,Java,Thread Safety,我有两个线程,一个线程插入数据,第二个线程检索数据。 我得到了非常奇怪的结果 它是线程安全的吗 如果没有,如何修复 这是我的循环缓冲区: private int mBufferSize; private int startPointer = 0; private int endPointer = 0; private int bufferSize = 0; private String[] buffer; public BBuffer(int size)
我得到了非常奇怪的结果 它是线程安全的吗 如果没有,如何修复 这是我的循环缓冲区:
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;
}
}
不,它不是线程安全的。
如果从两个不同的线程调用getData()
和addData()
,那么您100%肯定会遇到问题,主要是因为bufferSize
将由两个线程访问;一个调用getData()
,另一个调用addData()
。
要解决此问题,应首先获取锁,然后再修改bufferSize
成员变量。
应该可以帮助您开始使用线程和锁,以及如何保护共享资源。不,它不是线程安全的。
如果从两个不同的线程调用getData()
和addData()
,那么您100%肯定会遇到问题,主要是因为bufferSize
将由两个线程访问;一个调用getData()
,另一个调用addData()
。
要解决此问题,应首先获取锁,然后再修改bufferSize
成员变量。
应该可以帮助您开始使用线程和锁以及如何保护共享资源。为此,您使用了一个信号量,因为您使用的是基本数组。ArrayList可以用作线程安全的方法。但是在您的实现中,您希望创建一个信号量,然后在每个使用缓冲区的方法中调用semaphore.aquire(),完成后调用semaphore.release(),因为您使用的是基本数组,所以要使用一个信号量。ArrayList可以用作线程安全的方法。但是在您的实现中,您希望创建一个信号量,然后在每个使用缓冲区的方法中调用semaphore.aquire(),完成后调用semaphore.release()根本不是线程安全的 您只需在4个方法的声明中添加
synchronized
关键字。幸运的是,这样一个简单的解决方案适用于您的类,因为情况并非总是如此
一个潜在的棘手问题是
getData
返回的String[]
。每次调用时都会创建一个新数组,这样就不会有任何问题,但如果它返回了对内部数组的引用,则同步会很复杂。根本不是线程安全的
您只需在4个方法的声明中添加synchronized
关键字。幸运的是,这样一个简单的解决方案适用于您的类,因为情况并非总是如此
一个潜在的棘手问题是
getData
返回的String[]
。每次调用时都会创建一个新数组,这样就不会有任何问题,但如果它返回了对内部数组的引用,则同步会很复杂。这是家庭作业吗?如果是这样的话,你能给它贴上“家庭作业”的标签吗?我怀疑addData和getData应该是同步的。如果一个线程调用加法,而另一个线程在get中,或者VICA反之亦然,比如说,在DIV操作符的毛茸茸的数学的中间,坏事可能发生。这是一个作业吗?如果是这样的话,你能给它贴上“家庭作业”的标签吗?我怀疑addData和getData应该是同步的。如果一个线程调用加法,而另一个线程在get中,或者VICA反之亦然,比如说,在DIV操作符的毛茸茸的数学的中间,坏的事情可能发生。请解释一下为什么同步关键字在这种情况下足够了?thanksEach方法使对象保持一致状态。反例是一个具有方法setFirstName
和setLastName
的类;即使这两种方法都是同步的,在某些时间段内,对象的状态也不一致,其名字与姓氏不一致。请您进一步解释一下,为什么在这种情况下同步关键字就足够了?thanksEach方法使对象保持一致状态。反例是一个具有方法setFirstName
和setLastName
的类;即使这两个方法都是同步的,您也会有一些时间段,其中对象的状态不一致,其名字与姓氏不一致。