자바 다 중 스 레 드 에서 자원 경쟁 을 해결 하 는 7 가지 방법 에 대한 상세 한 설명
일반적인 상황 에서 다 중 스 레 드 프로 그래 밍 과 관련 되면 프로그램의 복잡성 이 현저히 상승 하고 성능 이 현저히 떨 어 지 며 BUG 가 나타 날 확률 이 크게 높아진다.
다 중 스 레 드 프로 그래 밍 은 프로그램 을 병행 하여 실행 하고 데이터 처리 능력 을 향상 시 키 는 것 이 목적 이지 만 대부분 상황 에서 공유 자원 의 경쟁 과 관련 되 기 때문에 자원 을 수정 하 는 것 이다.
대상 시 잠 금 처 리 를 해 야 합 니 다.그러나 자물쇠 의 실현 에는 여러 가지 방법 이 있 습 니 다.다음은 C\#언어 에서 몇 가지 자물쇠 의 실현 과 그 성능 표현 을 알 아 보 겠 습 니 다.
1.c\#아래 의 몇 가지 자물쇠 활용 방식
1.임계 구역 은 다 중 스 레 드 에 대한 직렬 화 를 통 해 공공 자원 이나 코드 를 방문 하고 속도 가 빠 르 며 데이터 접근 을 제어 하기에 적합 합 니 다.
private static object obj = new object();
private static int lockInt;
private static void LockIntAdd()
{
for (var i = 0; i < runTimes; i++)
{
lock (obj)
{
lockInt++;
}
}
}
c\#의 lock 문법 은 임계 구역(Monitor)의 문법 사탕 입 니 다.이것 은 대략 90%이상 의.net 프로그래머 가 먼저 생각 하 는 자물쇠 입 니 다.그러나 대부분 사람들 은 알 고 있 을 뿐 입 니 다.이런 문법 이 있 는데 사실은 임계 구역 의 방식 으로 자원 경쟁 을 처리 하 는 것 인지 모르겠다.
2.상호 배척 량 은 공유 자원 에 대한 공동 방문 을 조율 하기 위해 디자인 된 것 이다.
c\#에 Mutex 류 가 있 습 니 다.System.Threading 네 임 스페이스 에서 Mutex 는 바로 상호 배척 량 입 니 다.상호 배척 량 은 다 중 스 레 드 간 의 자원 경쟁 만 처리 할 수 있 는 것 이 아니 라 처리 할 수 있 습 니 다.
프로 세 스 간 의 자원 경쟁 은 기능 이 비교적 강하 지만 비용 도 많 고 성능 도 비교적 낮다.
private static Mutex mutex = new Mutex();
private static int mutexInt;
private static void MutexIntAdd()
{
for (var i = 0; i < runTimes; i++)
{
mutex.WaitOne();
mutexInt++;
mutex.ReleaseMutex();
}
}
3.신 호 량 은 유한 한 수량 을 가 진 사용자 자원 을 제어 하기 위해 설계 되 었 다.
private static Semaphore sema = new Semaphore(1, 1);
private static int semaphoreInt;
private static void SemaphoreIntAdd()
{
for (var i = 0; i < runTimes; i++)
{
sema.WaitOne();
semaphoreInt++;
sema.Release();
}
}
4.이벤트:스 레 드 에 일부 사건 이 발생 했 음 을 알 리 고 후속 작업 의 시작 을 시작 합 니 다.
public static AutoResetEvent autoResetEvent = new AutoResetEvent(true);
private static int autoResetEventInt;
private static void AutoResetEventIntAdd()
{
for (var i = 0; i < runTimes; i++)
{
if (autoResetEvent.WaitOne())
{
autoResetEventInt++;
autoResetEvent.Set();
}
}
}
5.읽 기와 쓰기 자물쇠,이 자 물 쇠 는 다른 프로그램 이 쓰 고 있 는 상황 에서 자원 을 읽 을 수 있 기 때문에 자원 이 더러 운 읽 기 를 허용 한다 면 이 걸 사용 하 는 것 이 좋 습 니 다.
private static ReaderWriterLockSlim LockSlim = new ReaderWriterLockSlim();
private static int lockSlimInt;
private static void LockSlimIntAdd()
{
for (var i = 0; i < runTimes; i++)
{
LockSlim.EnterWriteLock();
lockSlimInt++;
LockSlim.ExitWriteLock();
}
}
6.원자 잠 금,원자 조작 Interlocked.CompareExchange 를 통 해"잠 금 없 음"경쟁 실현
private static int isLock;
private static int ceInt;
private static void CEIntAdd()
{
//long tmp = 0;
for (var i = 0; i < runTimes; i++)
{
while (Interlocked.CompareExchange(ref isLock, 1, 0) == 1) { Thread.Sleep(1); }
ceInt++;
Interlocked.Exchange(ref isLock, 0);
}
}
7.원자 성 조작 은 일종 의 특례 로 야외 원자 성 조작 자체 가 타고 난 라인 이 안전 하기 때문에 자 물 쇠 를 채 울 필요 가 없다.
private static int atomicInt;
private static void AtomicIntAdd()
{
for (var i = 0; i < runTimes; i++)
{
Interlocked.Increment(ref atomicInt);
}
}
8.자 물 쇠 를 넣 지 않 고 자 물 쇠 를 넣 지 않 으 면 다 중 스 레 드 에서 실 행 된 결과 가 틀 렸 을 것 입 니 다.여기에 붙 여 성능 을 비교 해 보 겠 습 니 다.
private static int noLockInt;
private static void NoLockIntAdd()
{
for (var i = 0; i < runTimes; i++)
{
noLockInt++;
}
}
2.성능 테스트1.테스트 코드,실행 1000,10000,100000,1000000 회
private static void Run()
{
var stopwatch = new Stopwatch();
var taskList = new Task[loopTimes];
//
Console.WriteLine();
Console.WriteLine($" :{loopTimes}");
Console.WriteLine($" :{runTimes}");
Console.WriteLine($" :{runTimes * loopTimes}");
// AtomicIntAdd
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { AtomicIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("AtomicIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{atomicInt}");
// CEIntAdd
taskList = new Task[loopTimes];
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { CEIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("CEIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{ceInt}");
// LockIntAdd
taskList = new Task[loopTimes];
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { LockIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("LockIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{lockInt}");
// MutexIntAdd
taskList = new Task[loopTimes];
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { MutexIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("MutexIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{mutexInt}");
// LockSlimIntAdd
taskList = new Task[loopTimes];
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { LockSlimIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("LockSlimIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{lockSlimInt}");
// SemaphoreIntAdd
taskList = new Task[loopTimes];
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { SemaphoreIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("SemaphoreIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{semaphoreInt}");
// AutoResetEventIntAdd
taskList = new Task[loopTimes];
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { AutoResetEventIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("AutoResetEventIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{autoResetEventInt}");
// NoLockIntAdd
taskList = new Task[loopTimes];
stopwatch.Restart();
for (var i = 0; i < loopTimes; i++)
{
taskList[i] = Task.Factory.StartNew(() => { NoLockIntAdd(); });
}
Task.WaitAll(taskList);
Console.WriteLine($"{GetFormat("NoLockIntAdd")}, :{stopwatch.ElapsedMilliseconds} , :{noLockInt}");
Console.WriteLine();
}
2.라인:103.라인:50
3.총화
1)각종 테스트 에서 자 물 쇠 를 채 우지 않 는 것 이 가장 빠 를 것 이 므 로 자원 경쟁 으로 인해 자 물 쇠 를 채 워 운행 하 는 것 을 피한다.
2)다 중 스 레 드 에서 Interlocked.CompareExchange 는 항상 우수한 성능 을 보 여 2 위 를 차지 했다.
3)세 번 째 lock,임계 구역 도 좋 은 성능 을 보 였 으 니 다른 사람 이 lock 성능 이 낮다 고 말 할 때 반박 하 세 요.
4)네 번 째 는 원자 변수(Atomic)작업 이지 만 현 재 는 변수의 자체 증가 와 감소 만 지원 하고 적용 성 이 강하 지 않다.
5)다섯 번 째 읽 기와 쓰기 자물쇠(Reader Writer LockSlim)의 표현 도 괜 찮 고 읽 을 것 이 없 는 것 을 지원 하 며 실용성 이 좋 습 니 다.
6)남 은 신 호 량,사건,상호 배척 량 등 세 가지 성능 이 가장 떨어진다.물론 그들 은 각자 의 적용 범 위 를 가지 고 있 지만 자원 경쟁 을 처리 하 는 데 있어 서 좋 지 않다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.