【问题标题】:Java synchronized statementJava同步语句
【发布时间】:2013-06-20 13:38:02
【问题描述】:

我需要一个这样的线程安全数组列表。

public class BookingList {

  private List<Booking> bookings;

  public BookingList() {
      bookings = Collections.synchronizedList(new ArrayList<Booking>());
  }

  @Override
  public void addBooking(Booking booking)
  {
    synchronized (bookings) {
        bookings.add(booking);
    }   
  }

  @Override
  public void removeBooking(Booking booking)
  {
    synchronized (bookings) {
        bookings.remove(booking);
    }   
  }
}

根据 java doc,使用 Collections.synchronizedList 时需要同步对列表的每次访问。我不确定我的同步块是否会这样做?

  1. 我对同步块的使用是否等同于

    ...
    public synchronized void addBooking(Booking booking) {
      bookings.add(booking);
    }
    
  2. 我应该使用这样的 ReentrantLock

    private Lock lock = new ReentrantLock();
    public void addBooking(Booking booking) {
      try {
        lock.lock;
        bookings.add(booking);
      } finally {
        lock.release();
      }
    }
    

【问题讨论】:

标签: java synchronization reentrantlock synchronized-block


【解决方案1】:

您不需要同步 简单操作,例如 addremove,因为这是由实现在内部处理的,这正是原因您使用它们:避免自己处理同步

但对于 复合操作,如 迭代多次删除 超出内部同步范围,您必须提供自己的锁定机制.

【讨论】:

  • 但是我有一个没有同步的 add 方法和一个进行某种迭代的方法。然后我只对迭代方法进行同步。 Java怎么知道add和iteration-method的同步是一样的呢?澄清一下:我看到 2 个不同的线程不能同时调用“add”,但是一个线程可以调用 add 而另一个调用 iteration.method?
  • 如果您在整个列表上同步,您应该没有任何问题:synchronized(bookings){ // iterate ... } 因为 add 方法和您的迭代都将使用相同的锁。
【解决方案2】:

回答您的问题:

1:

public synchronized void addBooking(Booking booking) {
   bookings.add(booking);
}

等价于

public void addBooking(Booking booking) {
   synchronized (this){
       bookings.add(booking);
   }
}

2:对于您的示例,您不应使用ReentrantLock。调用已使用Collections.synchronizedList() 初始化的列表的方法是线程安全的,无需使用进一步的synchronized 或其他锁定机制。其余的请参见@Pragmateek 的回答。

【讨论】:

  • this.class 应该是这样的 :)
  • 是的。我改变了它。 this.class 将用于静态方法。
  • 谢谢.. 这很有道理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-29
  • 1970-01-01
相关资源
最近更新 更多