2016-08-23 3 views
0

DB 테이블을 업데이트하는 여러 가지 방법이있는 DAO 클래스가 있습니다. 이 메소드는 많은 다른 순서로 코드베이스의 여러 곳에서 호출됩니다.하나의 스레드가 클래스에 있음 보장

public class Dao { 
    public synchronized updateA() 
    public synchronized updateB() 
    public synchronized updateC() 
    public synchronized getA() 
    public synchronized getB() 
    public synchronized getC() 
} 

내가 Class1에 전화하고자하는 문제에 봉착 getA(), getB() 및 순서 getC(). 3 개의 테이블 A, B, C가 관련되어 있으므로 어느 시점에서 상태를 동기화해야합니다.

그러나 Class1이 getA()을 호출하고 getB()을 호출하기 전에 다른 스레드의 Class2가 점프하고 updateB()을 호출하여 문제가 발생합니다.

스레드가있는 동안 전체 DAO 클래스를 잠글 수 있으며 끝날 때 잠금을 해제 할 수 있습니까?

DAO 클래스에 정적 ReentrantLock을 넣고 Class1에서 잠그려고했으나 거기에서 어떻게 가는지 잘 모르겠습니다.

나는 다음과 같은까지 왔 :

public class Class1 { 
    public void check() { 
    dao.daoLock.lock(); 
    dao.getA(); 
    dao.getB(); 
    dao.getC(); 
    dao.daoLock.unlock(); 
    } 
} 

public class Dao { 
    public static final daoLock = new ReentrantLock(); 
    public synchronized updateA() { 
    daoLock.lock(); 
    // Do stuff... 
    } 
    public synchronized updateB() { 
    daoLock.lock(); 
    // Do stuff... 
    } 
    public synchronized updateC() { 
    daoLock.lock(); 
    // Do stuff... 
    } 
    public synchronized getA() { 
    daoLock.lock(); 
    // Do stuff... 
    } 
    public synchronized getB() { 
    daoLock.lock(); 
    // Do stuff... 
    } 
    public synchronized getC() { 
    daoLock.lock(); 
    // Do stuff... 
    } 
} 

나는 잠금 해제의 위치에 대한 확실 해요. DAO 클래스의 각 메소드에 넣으면 다른 쓰레드를 넣을 수 있지 않을까요?

더 좋은 해결책이 있습니까?

+0

A와 B를 원자 적으로 업데이트하는'synchronized updateAandB()'메소드를 추가 할 수 있습니까?또는 호출 사이트 (아마도 클래스 인스턴스 자체)에서 동기화가 수행되도록 정책을 변경 하시겠습니까? – assylias

답변

3

클라이언트 측 데이터베이스 액세스를 근본적으로 잘못된 위치로 설정하려고합니다. 그 동안에 다른 고객이 글을 쓰면 어떨까요?

거래 (MySQL, PostgreSQL)를 사용하여, 데이터베이스 자체에 동기화 이런 종류의를두고하는 것이 좋습니다.

여러 클라이언트를 보유하고 있지는 않지만 결코 사용하지 않더라도 트랜잭션을 사용하는 것이 더 나은 솔루션입니다. 그렇지 않으면, 당신의 모든 쓰레드는 단지 읽는 중이더라도 원칙적으로 동시에 일어날 수 있습니다.

1

토마스 (Thomas)의 좋은 답변 외에도 여기에서 볼 가치가있는 또 다른 측면이 있습니다. 인터페이스은 올바른 작업을 쉽게하기 위해 작성해야합니다. 잘못된 것을하기가 어렵습니다.

의미 :(), b(), c()를 순서대로 호출하고 "전체 잠김 방식"으로 호출해야하는 작업이있는 경우 : 인터페이스에 a, b, c가있는 대신, 정확히 메서드 abc() ...를 사용하면 잠금을 획득하고, a, b, c를 호출하고 잠금을 해제합니다.

그럼 다시 돌아가서 SOLID 관점에서 수업의 인터페이스를 살펴보아야합니다. 또는 더 구체적 - 사물의 "단일 책임 원칙"측면에서 고려하십시오.

즉 : 하나의 클래스는 완전히 "분리 된"메소드를 제공합니다. 심지어 그 중 일부는 "명확한 디자인 냄새"인 "매우 구체적인 방식으로 함께 사용"될 필요가 있습니다. 다시 말해서이 디자인을 다시 검토하는 것이 좋습니다.

관련 문제