Reputation:
when I have two LinkedLists, product and price declared on the top of a class. And there are some threads who can write to this lists, I must(!) safe this Lists with a Mutex (synchronized). Is the following correct and is there a better way?
public class Shop extends Thread {
volatile LinkedList<String> product = new LinkedList<String>();
volatile LinkedList<Float> price = new LinkedList<Integer>();
public class Inserter extends Thread {
@Override
public void run() {
synchronized (product) {
product.add(i1);
}
synchronized (price) {
price.add(i2);
}
}
}
}
Upvotes: 0
Views: 1712
Reputation: 115378
No, your code is incorrect. You are using separate synchronized blocks for update of your separate collections. This means that you can fail on data incosistancy when new product has been already added by price has not be attached yet. So, if other thread does something like this:
int n = product.size() -1;
Product prod = product.get(n); //OK
Price pr = price.get(n); // throws exception
exception will be thrown.
Better solution is to synchronized both operation using 1 lock:
Object productPriceLock = new Object();
.............
public void run() {
synchronized (productPriceLock) {
product.add(i1);
price.add(i2);
}
}
This code is better but a little bit ugly. Better solution is not to hold parallel colecitons but create special class that holds both product and price:
class Deal {
private final Product product;
private final Price price;
public Deal(Product product, Price price) { ... }
.......
}
Please pay attention that the class Deal
is immutable.
Now you can put it into one collection and if you want synchronize it. But better use one of available concurrent collections. It is much more efficient and less error prone.
Upvotes: 0
Reputation: 542
I have few comments
code in this is better
synchronized (product) {
product.add(i1);
synchronized (price) {
price.add(i2);
}
}
2 idea
Synchronized the Inserter.class
synchronized(Inserter.class){
product.add(i1)
price.add(i2)
}
Synchronized on a global object. Apply to the case which Inserter is not the only class to do the manipulation.
Object objLock = new Object()
...
synchronized(objLock){
product.add(i1)
price.add(i2)
}
Upvotes: 0
Reputation: 85779
Decorate your LinkedList
using Collections#synchronizedList
instead:
volatile List<String> product = Collections.synchronizedList(new LinkedList<String>());
Upvotes: 2