Java同步对象?

时间:2011-12-21 20:32:58

标签: java multithreading concurrency synchronization thread-safety

我在java中有一个类,它读取UDP数据包并将它们放在一个对象中(基本上是无限循环)。然后在多个单独的线程中访问此对象,但显然,由于它是同时填充的,因此所有这些getter / setter都采用同步方法。问题是,现在这些getter有这样的代码:

public synchronized SomeObject exampleGetter() {
    if(this.isReceiving)
        return oldCachedObject;
    else
        return currentObject;
}

显然,这不是最好的做事方式,所以我应该如何编写方法(许多不同的方法),将对象完全锁定到一个线程并阻塞其他线程(包括创建的线程)首先是对象)?我看了一下synchronized块,但是我对于“锁定对象”有什么影响感到困惑,是那个在给定时间可以访问块的对象?任何意见,将不胜感激。谢谢!

3 个答案:

答案 0 :(得分:5)

synchronized关键字在整个对象实例上同步,而不仅仅是setter。我宁愿选择细粒度锁定策略或更好...使用线程安全数据结构来存储和获取接收到的数据。我个人喜欢BlockingQueue<T>,其中T是您在网络上收到的数据类型。

假设您正在通过套接字接收Object

public class ReceivedDataHolder{
    BlockingQueue<Object> dataBuffer = new LinkedBlockingQueue<Object>();
    //...
    public void dataReceived(Object data){
       dataBuffer.offer(data);
    } 

    public Object getReceivedData(){
       return dataBuffer.take();
    }
}

在您的套接字中,无论何时收到数据,都可以执行此操作:

receivedDataHolder.dataReceived(object);

任何想要获取数据的线程都应该这样做:

receivedDataHolder.getReceivedData();

后一个方法调用将阻塞调用线程,直到队列中有一个元素可用(检查this以获取更多详细信息)

我希望这会有所帮助

答案 1 :(得分:2)

答案 2 :(得分:0)

java中的所有对象都有一些称为内部锁的东西,如果任何线程想对任何对象进行任何操作,那么它需要获取该对象的内部锁。它将保证在任何给定时间只有一个线程处理您的代码块。

一个线程可以获取对任何对象的锁定,如果该对象没有被任何其他线程锁定,如果它被锁定,那么该线程将等到另一个线程释放该对象的锁定。

如果您使用synchronized块,您的代码将有点像这样

public void SomeObject exampleGetter() {

synchronized(this)
{


if(this.isReceiving)
        return oldCachedObject;
    else
        return currentObject;


}

在这种情况下,当你的线程进入同步块时,如果任何其他线程对此对象有锁定,那么它将等待该线程释放锁定。如果该对象是空闲的,那么你的线程将获得对该对象的锁定并执行操作,然后释放该对象的锁定。

有关同步块,方法和内部锁的更多信息,请参阅 http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

我希望它能帮到你:)。