简体   繁体   English

Java中的同步LinkedList

[英]synchronized LinkedList in Java

when I have two LinkedLists, product and price declared on the top of a class. 当我有两个LinkedLists时,在类的顶部声明了product和price。 And there are some threads who can write to this lists, I must(!) safe this Lists with a Mutex (synchronized). 并且有一些线程可以写入此列表,我必须(!)使用Mutex(同步的)保护此列表的安全。 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);
    }
   }
  }
}

改用Collections#synchronizedList装饰您的LinkedList

volatile List<String> product = Collections.synchronizedList(new LinkedList<String>());

I have few comments 我的评论很少

  1. I don't see the meaning of volatile... It is a Reference type pointing to the same list all the time, even if you add/remove elements from the list. 我看不到volatile的含义。这是一个引用类型,始终指向同一列表,即使您从列表中添加/删除元素也是如此。 (This is a mutable list) (这是一个可变的列表)
  2. When 1 threads want to add (product1, price1) and another thread add (product2, price2), the order of both list may out of order. 当1个线程要添加(product1,price1)而另一个线程要添加(product2,price2)时,两个列表的顺序可能不正确。 eg 例如
    Product = {product1, product2} and Price = {price 2, price1}. 产品= {产品1,产品2},价格= {价格2,价格1}。 You can add a sleep in one thread and you will see. 您可以在一个线程中添加睡眠,您将看到。

code in this is better 这样的代码更好

synchronized (product) {
     product.add(i1);
     synchronized (price) {
         price.add(i2);
    }
}

2 idea 2个主意

Synchronized the Inserter.class 同步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. 适用于Inserter不是唯一进行操作的类的情况。

Object objLock = new Object()
...
synchronized(objLock){
   product.add(i1)
   price.add(i2)
}

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: 更好的解决方案是使用1个锁同步两个操作:

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. 请注意,类别Deal是不可变的。

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. 它效率更高,出错率更低。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM