Java 我应该使用原子整数还是同步

Java 我应该使用原子整数还是同步,java,multithreading,concurrency,synchronization,atomic,Java,Multithreading,Concurrency,Synchronization,Atomic,我对在代码中使用原子/易失性/同步有点困惑。 假设我在一家书店里有一个图书信息对象,例如,当库存中的数量只有1时,可能会发生两个线程想要拿走同一本书的情况,我如何保证只有一个线程会拿走这本书? 我必须使用同步吗? 图书目录信息: package bgu.spl.mics.application.passiveObjects; import java.util.concurrent.atomic.AtomicInteger; /** * Passive data-object represe

我对在代码中使用原子/易失性/同步有点困惑。 假设我在一家书店里有一个图书信息对象,例如,当库存中的数量只有1时,可能会发生两个线程想要拿走同一本书的情况,我如何保证只有一个线程会拿走这本书? 我必须使用同步吗? 图书目录信息:

package bgu.spl.mics.application.passiveObjects;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Passive data-object representing a information about a certain book in the inventory.
 * 
 * <p>
 *
 */
public class BookInventoryInfo {

    //The title of the book, his amount in the inventory and the price
    private String bookTitle;
    private AtomicInteger amountInInventory;
    private int price;

    public BookInventoryInfo(String bookTitle, int amountInInventory, int price) {
        this.bookTitle = bookTitle;
        this.price = price;
        this.amountInInventory = new AtomicInteger(amountInInventory);
    }


    /**
     * Retrieves the title of this book.
     * <p>
     * @return The title of this book.   
     */
    public String getBookTitle() {
        return this.bookTitle;
    }

    /**
     * Retrieves the amount of books of this type in the inventory.
     * <p>
     * @return amount of available books.      
     */
    public int getAmountInInventory() {
        return this.amountInInventory.get();
    }

    /**
     * Retrieves the price for  book.
     * <p>
     * @return the price of the book.
     */
    public int getPrice() {
        return this.price;
    }

    public void reduceAmountInInventory() {
        this.amountInInventory.decrementAndGet();
    }
}

您应该使用
synchronized
,因为使用AtomicInteger并不像乍一看那样简单。虽然AtomicInteger上的单个操作是线程安全的,但使用多个操作可能不是。你的例子很好。说你有

// say it start at 1
Thread1: if(book.getAmountInInventory > 0)
Thread2: if(book.getAmountInInventory > 0)
Thread1: book.amountInInventory--
Thread2: book.amountInInventory--
现在的金额是-1

如果使用
synchronized
,则在整个操作中保持锁定会简单得多

synchronized (book) {
    if(book.getAmountInInventory > 0) // no chance for a race condition here.
    {
        book.amountInInventory--
    }

原子整数在这里是不够的。虽然它允许您以原子方式减少库存中的副本数量,但这还不够——您不需要以原子方式减少它,还需要添加一些自定义逻辑

我会使用普通的
int
,并使用显式
同步的
块或方法来保护其修改:

public class BookInventoryInfo {

    private String bookTitle;
    private int amountInInventory;
    private int price;

    public synchronized void checkOut() {
        if (amountInInventory <= 0) {
            throw new BookCheckoutException("No book in inventory");
        }
        amountInInventory--;
    }

    // All the other methods...
}
公共类BookInventoryInfo{
私有字符串书名;
私营企业;
私人int价格;
公共同步的无效签出(){

如果(amountinventory作为同步的替代方案,您还可以使用:

如果更新时
amountInventory
的值仍然是
a
,则这只会减小该值。
compareAndSet
的返回值指示该值是否已更改

您可以将其包装成一个循环,类似于:

while (true) {
  int a = book.amountInventory.get();
  if (a == 0) {
    return false;  // To mean "no book in inventory";
  }
  if (book.amountInInventory.compareAndSet(a, a - 1)) {
    return true;  // To mean "there was a book in inventory, and it was removed".
  }
}

谢谢,所以使用synchronize,我不需要担心int值只在缓存中更新而不在ram中更新的可能性?
int a = book.amountInventory.get();
if (a > 0) {
  boolean updated = book.amountInInventory.compareAndSet(a, a - 1);
}
while (true) {
  int a = book.amountInventory.get();
  if (a == 0) {
    return false;  // To mean "no book in inventory";
  }
  if (book.amountInInventory.compareAndSet(a, a - 1)) {
    return true;  // To mean "there was a book in inventory, and it was removed".
  }
}