当我有两个LinkedLists时,产品和价格在类的顶部声明。并且有一些线程可以写入此列表,我必须(!)使用互斥锁(同步)保护此列表。以下是否正确并且有更好的方法吗?
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);
}
}
}
}
答案 0 :(得分:2)
使用Collections#synchronizedList
装饰您的LinkedList
:
volatile List<String> product = Collections.synchronizedList(new LinkedList<String>());
答案 1 :(得分:0)
我的评论很少
这里的代码更好
synchronized (product) {
product.add(i1);
synchronized (price) {
price.add(i2);
}
}
2个想法
同步Inserter.class
synchronized(Inserter.class){
product.add(i1)
price.add(i2)
}
在全局对象上同步。适用于Inserter不是唯一一个进行操作的类。
Object objLock = new Object()
...
synchronized(objLock){
product.add(i1)
price.add(i2)
}
答案 2 :(得分:0)
不,您的代码不正确。您正在使用单独的同步块来更新单独的集合。这意味着,如果尚未按价格添加新产品,则可能会导致数据失效。所以,如果其他线程做了这样的事情:
int n = product.size() -1;
Product prod = product.get(n); //OK
Price pr = price.get(n); // throws exception
将抛出异常。
更好的解决方案是使用1个锁来同步两个操作:
Object productPriceLock = new Object();
.............
public void run() {
synchronized (productPriceLock) {
product.add(i1);
price.add(i2);
}
}
这段代码更好但有点难看。更好的解决方案不是保持平行的colecitons,而是创建一个既包含产品又包含价格的特殊类:
class Deal {
private final Product product;
private final Price price;
public Deal(Product product, Price price) { ... }
.......
}
请注意班级Deal
是不可变的。
现在你可以把它放到一个集合中,如果你想同步它。但最好使用可用的并发集合之一。它更有效,更不容易出错。