리턴 문이 잠금 내부 또는 외부에 있어야합니까?
방금 내 코드의 어느 곳에서 잠금 내부와 외부에 return 문이 있음을 깨달았습니다. 어느 것이 최고입니까?
1)
void example()
{
lock (mutex)
{
//...
}
return myData;
}
2)
void example()
{
lock (mutex)
{
//...
return myData;
}
}
어느 것을 사용해야합니까?
기본적으로 코드가 단순 해집니다. 단일 종료 지점은 이상적이지만, 코드를 달성하기 위해 코드를 구부리지 않습니다 ... 그리고 대안이 로컬 변수 (잠금 외부)를 선언하고 초기화하면 (잠금 내부) 그런 다음 (잠금 외부에) 반환하면 잠금 내부의 간단한 "반환 foo"가 훨씬 간단하다고 말하고 싶습니다.
IL의 차이점을 보여주기 위해 코드를 작성해 보겠습니다.
static class Program
{
static void Main() { }
static readonly object sync = new object();
static int GetValue() { return 5; }
static int ReturnInside()
{
lock (sync)
{
return GetValue();
}
}
static int ReturnOutside()
{
int val;
lock (sync)
{
val = GetValue();
}
return val;
}
}
(나는 그것이 ReturnInside
더 간단하고 깨끗한 C # 비트 라고 행복하게 주장 할 것 입니다)
그리고 IL (릴리스 모드 등)을보십시오.
.method private hidebysig static int32 ReturnInside() cil managed
{
.maxstack 2
.locals init (
[0] int32 CS$1$0000,
[1] object CS$2$0001)
L_0000: ldsfld object Program::sync
L_0005: dup
L_0006: stloc.1
L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
L_000c: call int32 Program::GetValue()
L_0011: stloc.0
L_0012: leave.s L_001b
L_0014: ldloc.1
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)
L_001a: endfinally
L_001b: ldloc.0
L_001c: ret
.try L_000c to L_0014 finally handler L_0014 to L_001b
}
method private hidebysig static int32 ReturnOutside() cil managed
{
.maxstack 2
.locals init (
[0] int32 val,
[1] object CS$2$0000)
L_0000: ldsfld object Program::sync
L_0005: dup
L_0006: stloc.1
L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
L_000c: call int32 Program::GetValue()
L_0011: stloc.0
L_0012: leave.s L_001b
L_0014: ldloc.1
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)
L_001a: endfinally
L_001b: ldloc.0
L_001c: ret
.try L_000c to L_0014 finally handler L_0014 to L_001b
}
So at the IL level they are [give or take some names] identical (I learnt something ;-p). As such, the only sensible comparison is the (highly subjective) law of local coding style... I prefer ReturnInside
for simplicity, but I wouldn't get excited about either.
It doesn't make any difference; they're both translated to the same thing by the compiler.
To clarify, either is effectively translated to something with the following semantics:
T myData;
Monitor.Enter(mutex)
try
{
myData= // something
}
finally
{
Monitor.Exit(mutex);
}
return myData;
I would definitely put the return inside the lock. Otherwise you risk another thread entering the lock and modifying your variable before the return statement, therefore making the original caller receive a different value than expected.
If think the lock outside looks better, but be careful if you end up changing the code to:
return f(...)
If f() needs to be called with the lock held then it obviously needs to be inside the lock, as such keeping returns inside the lock for consistency makes sense.
It depends,
I am going to go against the grain here. I generally would return inside of the lock.
Usually the variable mydata is a local variable. I am fond of declaring local variables while I initialize them. I rarely have the data to initialize my return value outside of my lock.
So your comparison is actually flawed. While ideally the difference between the two options would be as you had written, which seems to give the nod to case 1, in practice its a little uglier.
void example() {
int myData;
lock (foo) {
myData = ...;
}
return myData
}
vs.
void example() {
lock (foo) {
return ...;
}
}
I find case 2 to be considerably easier to read and harder to screw up, especially for short snippets.
To make it easier for fellow developers to read the code I would suggest the first alternative.
For what it's worth, the documentation on MSDN has an example of returning from inside of the lock. From the other answers on here, it does appear to be pretty similar IL but, to me, it does seem safer to return from inside the lock because then you don't run the risk of a return variable being overwritten by another thread.
Outside looks cleaner.
lock() return <expression>
statements always:
1) enter lock
2) makes local (thread-safe) store for the value of the specified type,
3) fills the store with the value returned by <expression>
,
4) exit lock
5) return the store.
It means that value, returned from lock statement, always "cooked" before return.
Don't worry about lock() return
, do not listen to anyone here ))
참고URL : https://stackoverflow.com/questions/266681/should-a-return-statement-be-inside-or-outside-a-lock
'IT story' 카테고리의 다른 글
Eclipse의 모든 파일에서 문자열 바꾸기 (0) | 2020.06.30 |
---|---|
두 개의 같지 않은 부동 소수점 숫자를 빼서 0을 얻을 수 있습니까? (0) | 2020.06.30 |
Vim에서 regexp의 \ b와 같은 단어 경계 문자를 어떻게 검색합니까? (0) | 2020.06.30 |
파이썬에서 화면을 지우는 방법 (0) | 2020.06.30 |
AngularJS를 사용하여 ASP.NET 웹 API 메소드에서 파일 다운로드 (0) | 2020.06.30 |