2011-12-07 176 views
0

我有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

这是一个家庭作业?如果是这样,你可以用'家庭作业'来标记吗? – melihcelik

+0

我怀疑应该同步addData和getData。如果一个线程调用add,而另一个线程调用add,或者相反,也就是说,在div运算符的毛病数学中,可能会发生不好的事情。 – user949300

回答

0

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

0

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

3

根本不是线程安全的。

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

一个潜在的棘手问题是由getData返回的String[]。您在每次调用时创建一个新数组,因此您没有任何问题,但如果它已经返回了对内部数组的一些引用,则同步会很复杂。

+0

您能否解释一下为什么同步关键字在这种情况下足够了?谢谢 – kenny

+1

每种方法都使对象保持一致的状态。反例是一个带有setFirstName和setLastName方法的类;即使两个方法都是同步的,你也会有一些时间段,其中的对象是一个名字不对应于姓氏的不一致状态。 – toto2