2014-07-09 4 views
0

두 개의 LinkedLists, 제품 및 가격이 클래스 상단에 선언되어 있습니다. 그리고이 목록에 쓸 수있는 스레드가 있습니다. 뮤텍스 (동기화 된)를 사용하여이 목록을 안전해야합니다. 다음은 정확하고 더 좋은 방법이 있습니까?Java에서 LinkedList를 동기화했습니다.

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

실행 방법을 동기화 할 수 있습니까? –

+0

동기화 된 정적으로 클래스 수준 (인스턴스 수준 아님)에서 동기화 할 수 있습니다. – tom87416

답변

0

아니요, 코드가 잘못되었습니다. 별도의 동기화 된 블록을 사용하여 별도의 콜렉션을 업데이트하고 있습니다. 즉, 아직 가격이 붙지 않아서 신제품이 이미 추가 된 경우 데이터 손상에 실패 할 수 있습니다. 그래서 다른 스레드가 다음과 같이하면 :

int n = product.size() -1; 
Product prod = product.get(n); //OK 
Price pr = price.get(n); // throws exception 

예외가 throw됩니다.

Object productPriceLock = new Object(); 
............. 

public void run() { 
    synchronized (productPriceLock) { 
     product.add(i1); 
     price.add(i2); 
    } 
} 

이 코드는 잘하지만, 조금 못생긴 :

더 나은 솔루션은 1 개 잠금 장치를 사용하여 동기화 모두 작동하는 것입니다. 클래스 Deal는 불변이다

class Deal { 
    private final Product product; 
    private final Price price; 
    public Deal(Product product, Price price) { ... } 
    ....... 
} 

주의하십시오 : 더 나은 솔루션은 병렬 colecitons을 유지하지만, 제품과 가격을 모두 보유 특별 클래스를 생성하지 않는 것입니다.

이제 컬렉션을 하나의 컬렉션에 넣을 수 있으며 동기화하고 싶을 수도 있습니다. 그러나 사용 가능한 동시 콜렉션 중 하나를 사용하는 것이 좋습니다. 훨씬 효율적이고 오류가 발생하지 않습니다.

2

장식 당신의 LinkedList 대신 Collections#synchronizedList를 사용하여 :

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

오케이. 그러나 작업에서는 Inserter 클래스에서만 편집 할 수 있다고 말합니다. –

+0

'synchronizedList'로 장식하는지 여부에 관계없이 목록을 반복 할 때 동기화해야합니다. – marthursson

+0

@ user3302074 쓰기뿐만 아니라'remove'와 같은 다른 연산에서도 마찬가지입니다. –

0

내가 가진 몇 가지 의견

  1. 나는 휘발성의 의미를 볼 수 없습니다 ... 그것은 참조 타입 가리키는입니다 목록에서 요소를 추가/제거하더라도 항상 같은 목록에 추가 할 수 있습니다.
  2. 스레드가 1 개 (product1, price1)를 추가하려고하고 다른 스레드가 (product2, price2)을 추가하면 두 목록의 순서가 잘못 될 수 있습니다. 예 :
    제품 = {제품 1, 제품 2} 및 가격 = {가격 2, 가격 1}. 은 하나의 스레드에서 절전 모드를 추가 할 수 있습니다. 이에

코드는 전역 객체에 동기화 Inserter.class

synchronized(Inserter.class){ 
    product.add(i1) 
    price.add(i2) 
} 

를 동기화

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

이 더 나은 아이디어

입니다. Inserter가 조작을 수행하는 유일한 클래스가 아닌 경우에 적용하십시오.

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

귀하의 답변은 제 문제이므로 주문해야합니다. 하지만 교수님은 Inserter 클래스에 뮤텍스 만 추가해야한다고 말합니다. 그러나 그것은 문제를 해결하지 못합니다. –