【问题标题】:Java Synchronized Object?Java同步对象?
【发布时间】:2011-12-21 20:32:57
【问题描述】:

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

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

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

【问题讨论】:

标签: java multithreading concurrency synchronization thread-safety


【解决方案1】:

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

假设您通过套接字接收Objects:

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 了解更多详细信息)

希望对你有帮助

【讨论】:

  • BlockingQueue 是一个接口,所以new BlockingQueue&lt;Object&gt;(); 不会编译。必须使用实现接口的具体类,如ArrayBlockingQueue&lt;T&gt;LinkedBlockingQueue&lt;T&gt;,这是生产者/消费者最常用的具体阻塞队列。
  • @BrunoReis 确实是我的一个小错误。现在已经修复了
【解决方案2】:
【解决方案3】:

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

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

如果你使用同步块,你的代码会有点像这样

public void SomeObject exampleGetter() {

synchronized(this)
{


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


}

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

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

希望对你有帮助:)

【讨论】:

  • 完全没有意义:“如果任何线程想要对任何对象执行任何操作,那么它需要获取该对象的内在锁”。任何线程都可以对它知道的任何对象做任何事情,而无需获取任何类型的锁。
猜你喜欢
  • 2011-12-12
  • 2012-07-09
  • 1970-01-01
  • 2013-04-25
  • 2016-05-08
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多