Should I use atomic integer or sync

Sprint21 :

I've got a little confused about using atomic/volatile/sync in my code. Let's say I have an object of book info in a bookstore and for example, it may happen that two threads want to take the same book while the amount in the inventory is only 1, how can I promise that only one thread will take the book? do I have to use synchronize? BookInventoryInfo:

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();
    }
}

The way I want to take the book:

if(book.getAmountInInventory > 0)
{
    book.amountInInventory--
}
Peter Lawrey :

You should use synchronized as using AtomicInteger isn't as simple as it might appear at first glance. While individual operations on AtomicInteger are thread safe, using multiple operations might not be. Your example is a good one. say you have

// say it start at 1
Thread1: if(book.getAmountInInventory > 0)
Thread2: if(book.getAmountInInventory > 0)
Thread1: book.amountInInventory--
Thread2: book.amountInInventory--

The amount is now -1.

If you use synchronized it is much simpler to hold the lock for the whole operation

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=110848&siteId=1