2010-03-30 2 views
2

C#을 사용하여 ASP.NET 양식 웹 응용 프로그램을 개발하고 있습니다. 나는 고객을위한 새로운 주문을 만드는 방법을 가지고있다. 이것과 비슷하게 보입니다.ASP.NET 잠금 스레드 방법

private string CreateOrder(string userName) { 
     // Fetch current order 
     Order order = FetchOrder(userName); 
     if (order.OrderId == 0) { 
      // Has no order yet, create a new one 
      order.OrderNumber = Utility.GenerateOrderNumber(); 
      order.Save(); 
     } 
     return order; 
    } 

여기서 문제는, 두 개의 요청 (스레드)에서 한 고객이 다른 스레드가이 방법 안에도 동안이 방법은 두 번 호출되도록 할 수있다. 이로 인해 두 개의 주문이 생성 될 수 있습니다.

이 메소드를 올바르게 잠 그려면 어떻게해야합니까? 고객 당 한 번에 하나의 스레드에서만 실행할 수 있습니까?

시도해 보았습니다.

Mutex mutex = null; 
    private string CreateOrder(string userName) { 
     if (mutex == null) { 
      mutex = new Mutex(true, userName); 
     } 
     mutex.WaitOne(); 
     // Code from above 
     mutex.ReleaseMutex(); 
     mutex = null; 
     return order; 
    } 

이 방법은 작동하지만 때로는 WaitOne에 멈춰서 그 이유를 알 수 없습니다. 오류가 있습니까, 아니면 다른 방법으로 잠 가야합니까?

감사

답변

1

mutex ctor에 initiallyOwned에 대해 false을 전달하십시오. 뮤텍스를 생성하고 처음에 뮤텍스를 소유 한 경우 ReleaseMutex에 다시 전화해야합니다.

1

뮤텍스를 해제 할 때 항상 마지막으로 시도해야합니다. 또한 키가 올바른지 확인하십시오 (사용자 이름)

Mutex mutex = null; 
private string CreateOrder(string userName) { 
    mutex = mutex ?? new Mutex(true, userName); 
    mutex.WaitOne(); 
    try{ 
    // Code from above 
    }finally{ 
    mutex.ReleaseMutex(); 
    } 
    mutex = null; 
    return order; 
} 
+0

실제로 try/finally를 추가하지 않으므로 실수입니다. 그러나 불행하게도 그것은 문제의 해결책이 아닙니다. – Peter

0

제가 누락 된 경우가 아니면 일반 잠금 장치를 사용할 수 없습니까?

private object _locker = new object(); 

private string CreateOrder(string userName) 
{ 
    lock(_locker) 
    { 
     // Fetch current order 
     Order order = FetchOrder(userName); 
     if (order.OrderId == 0) 
     { 
      // Has no order yet, create a new one 
      order.OrderNumber = Utility.GenerateOrderNumber(); 
      order.Save(); 
     } 
     return order; 
    } 
} 
+0

이것은 내 마음에 솟아나는 것인데, 아마도 누군가 뮤텍스와 자물쇠의 차이점에 대해 우리에게 깨달을 수 있을까요? 자물쇠는 실제로 표면 아래의 뮤텍스라고 추측 할 수 있습니다. 더 많은 기능을 사용하기 위해 특별히 뮤텍스를 사용합니다. 그러나 이것은 단지 추측 일뿐입니다. – NibblyPig

+0

안녕하세요, 아마도 잠금을 설정해야합니다. 뮤텍스를 사용하는 배경은 사용자 이름별로 메소드를 잠그기 만하면된다는 것입니다. 나는 뮤텍스 (Mutex)라는 이름으로이를 달성하기를 원했다. – Peter

+0

전역 적입니다 - "프로세스 간 동기화에도 사용할 수있는 동기화 기본 형식". 동일한 PC의 프로세스간에 사용할 수 있습니다. 앱이 한 번만 시작되는지 확인하십시오. –

1

코드에서 지연 성 뮤직을 지연 생성 중입니다. 이것은 경쟁 조건으로 이어집니다.
예. 다른 스레드에서 WaitOne()을 호출 할 때 mutex가 부분적으로 만 생성 될 수 있습니다.
두 개의 뮤텍스 인스턴스를 만들 수도 있습니다.

예를 들어 Michael의 코드처럼 인스턴스를 열심히 만들면 이러한 상황을 피할 수 있습니다. (비 소유 상태로 초기화하십시오.)

뮤텍스는 커널 수준의 동기화 프리미티브입니다. 모니터보다 더 비쌉니다 (lock 사용).

+1

당신이 옳습니다, 어리석은 생각을하지 않았습니다. 그것은 내가 피하려고했던 동일한 문제 (부분적으로 구성된 명령들)로 이어진다 ... 답변에 대해 모두에게 감사한다. – Peter

0

필자는 웹 기반 응용 프로그램에서 항상 잠금을 피 했으므로 웹 서버가 스레드를 처리하고 대신 중복 된 탐지를 구축합니다.

CreateOrder를 잠그면 어떻게 될 것이라고 생각하십니까? 두 가지 주문을 동시에 만드는 것을 피할 수는 있지만 나중에 두 가지 주문을 만들어야합니다.

0

그것 쉽게이 작업을 수행합니다 :

지금처럼 어딘가에 클래스를 정의 :

public class MyLocks { 
    public static object OrderLock; 
    static MyLocks() { 
     OrderLock = new object(); 
    } 
} 

후 잠금 이렇게 사용하는 경우 :

lock(MyLocks.OrderLock) { 
    // put your code here 
} 

그것의 매우 복잡하지 다음.가중치를 정의하는 가벼운 무게는 여러 스레드에 걸쳐 메모리에있는 아주 작은 객체이므로 용도에 관계없이 잠금을 정의합니다.

관련 문제