깊이 분석 C\#스 레 드 동기 화
이 편 은 주로 스 레 드 동기 화 를 설명 한다.
공유 데이터 에 여러 스 레 드 가 동시에 접근 할 때 는 공유 데이터 가 파괴 되 지 않도록 스 레 드 로 동기 화해 야 합 니 다.여러 스 레 드 가 공유 데이터 에 동시에 접근 하지 않 으 면 스 레 드 동기 화 를 사용 하지 않 아 도 됩 니 다.
스 레 드 동기 화 에 도 문제 가 있 을 수 있 습 니 다.
가로막다
스 레 드 가 Sleep,Join,EndInvoke 를 호출 하면 스 레 드 가 막 힌 상태 입 니 다(Sleep 는 스 레 드 를 막 고 Join,EndInvoke 는 다른 스 레 드 를 막 습 니 다).cpu 에서 즉시 종료 합 니 다.(차단 상태의 스 레 드 는 cpu 를 소모 하지 않 습 니 다)
스 레 드 가 차단 과 비 차단 상태 에서 전환 할 때 몇 밀리초 의 시간 이 소 모 됩 니 다.
//Join
static void Main()
{
Thread t = new Thread (Go);
Console.WriteLine ("Main ....");
t.Start();
t.Join();// Main
Console.WriteLine ("Main , ...");
}
static void Go()
{
Console.WriteLine (" t Go ...");
}
//Sleep
static void Main()
{
Console.WriteLine ("Main ....");
Thread.CurrentThread.Sleep(3000);//
Console.WriteLine ("Main , ...");
}
//Task
static void Main()
{
Task Task1=Task.Run(() => {
Console.WriteLine("task ...");
Thread.Sleep(1000);
});
Console.WriteLine(Task1.IsCompleted);
Task1.Wait();// , Task1
Console.WriteLine(Task1.IsCompleted);
}
잠 금 추가(lock)잠 금 을 추가 하여 여러 스 레 드 가 같은 시간 에 하나의 스 레 드 만 이 방법 을 호출 할 수 있 고 다른 스 레 드 가 막 혔 습 니 다.
동기 화 대상 선택:
await
키 워드 를 사용 할 수 없습니다.잠 겨 있 는 방법 이 정적 이 라면 이 잠 금 은 정적 형식 이 어야 합 니 다.이렇게 하면 전체 국면 에서 이 방법 을 잠 그 고 이 종류 가 몇 개의 실례 가 있 든 지 간 에 줄 을 서서 실행 해 야 한다.
잠 겨 있 는 방법 이 정적 이 아니라면 정적 형식의 잠 금 을 사용 할 수 없습니다.잠 겨 있 는 방법 은 인 스 턴 스 에 속 하기 때문에 이 인 스 턴 스 가 잠 금 방법 을 호출 하여 손상 되 지 않 으 면 됩 니 다.서로 다른 인 스 턴 스 간 에는 잠 금 이 필요 없습니다.이 자 물 쇠 는 모든 인 스 턴 스 를 잠 그 는 방법 이 아니 라 이 인 스 턴 스 만 잠 그 는 방법 입 니 다.*
class ThreadSafe
{
private static object _locker = new object();
void Go()
{
lock (_locker)
{
......// (Static Method),
}
}
private object _locker2=new object();
void GoTo()
{
lock(_locker2)
// , , ,
}
}
동기 화 대상 은 lock 의 대상 을 겸 할 수 있 습 니 다.예:
class ThreadSafe
{
private List <string> _list = new List <string>();
void Test()
{
lock (_list)
{
_list.Add ("Item 1");
}
}
}
Monitorslock
은 사실 Monitors
의 간결 한 서법 이다.
lock (x)
{
DoSomething();
}
둘 은 사실 같다.
System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
DoSomething();
}
finally
{
System.Threading.Monitor.Exit(obj);
}
상호 배척 자물쇠(Mutex)상호 배척 자 물 쇠 는 서로 배척 하 는 동기 화 대상 으로 같은 시간 에 있 고 하나의 스 레 드 만 이 그것 을 얻 을 수 있다.프로 세 스 단계 의 스 레 드 동기 화 를 실현 할 수 있 습 니 다.
class Program
{
//
public static Mutex mutex = new Mutex();
static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
//
Thread test = new Thread(MutexMethod);
test.Start();
}
Console.Read();
}
public static void MutexMethod()
{
Console.WriteLine("{0} ", Thread.CurrentThread.Name);
mut.WaitOne();
Console.WriteLine("{0} ", Thread.CurrentThread.Name);
Thread.Sleep(1000);
Console.WriteLine("{0} ", Thread.CurrentThread.Name);
//
mut.ReleaseMutex();
Console.WriteLine("{0} ", Thread.CurrentThread.Name);
}
}
상호 배척 잠 금 은 서로 다른 프로 세 스 간 에 스 레 드 동기 화 를 실현 할 수 있다.상호 배척 자 물 쇠 를 사용 하여 한 번 에 한 프로그램 만 시작 할 수 있 는 기능 을 실현 합 니 다.
public static class SingleInstance
{
private static Mutex m;
public static bool IsSingleInstance()
{
//
Boolean isCreateNew = false;
try
{
m = new Mutex(initiallyOwned: true, name: "SingleInstanceMutex", createdNew: out isCreateNew);
}
catch (Exception ex)
{
}
return isCreateNew;
}
}
상호 배척 자물쇠 의 세 개의 매개 변 수 를 가 진 구조 함수lock
과 mutex
은 스 레 드 동기 화 를 실현 하여 한 번 에 한 스 레 드 만 실행 할 수 있 도록 확보한다.하지만 스 레 드 간 통신 은 이 루어 지지 않 는 다.스 레 드 가 서로 통신 해 야 한다 면 AutoResetEvent
,ManualResetEvent
을 사용 하여 신 호 를 통 해 서로 통신 해 야 한다.그것들 은 모두 두 가지 상태 가 있 는데,중지 상태 와 비 중지 상태 이다.비 종료 상태 에 있 을 때 만 스 레 드 가 막 힐 수 있 습 니 다.AutoResetEvent:
AutoResetEvent
구조 함 수 는 bool 형식의 매개 변 수 를 전달 할 수 있 고 false
은 AutoResetEvent
대상 의 초기 상 태 를 비 종료 로 설정 하 는 것 을 나타 낸다.true
표지 의 종료 상태 라면 WaitOne
방법 은 더 이상 스 레 드 를 막 지 않 을 것 이다.그러나 이 종 류 는 자동 으로 종료 상 태 를 비 종료 로 수정 하기 때문에 이후 WaitOne
방법 을 사용 하면 차단 된다.WaitOne
방법 이 AutoResetEvent
대상 상태 가 종료 되 지 않 으 면 이 방법 을 사용 하 는 스 레 드 를 차단 합 니 다.시간 을 지정 할 수 있 습 니 다.신 호 를 받 지 못 하면 false 로 돌아 갑 니 다.set
방법 으로 막 힌 스 레 드 를 방출 합 니 다.하지만 한 번 에 막 힌 스 레 드 만 풀 수 있 습 니 다.
class ThreadSafe
{
static AutoResetEvent autoEvent;
static void Main()
{
// AutoResetEvent
autoEvent = new AutoResetEvent(false);
Console.WriteLine(" ...");
Thread t = new Thread(DoWork);
t.Start();
Console.WriteLine(" sleep 1 ...");
Thread.Sleep(1000);
Console.WriteLine(" ...");
autoEvent.Set();
}
static void DoWork()
{
Console.WriteLine(" t DoWork , main ...");
autoEvent.WaitOne();
Console.WriteLine(" t DoWork main , ...");
}
}
출력주 스 레 드 실행...
주 스 레 드 sleep 1 초...
t 스 레 드 실행 DoWork 방법,기본 스 레 드 신 호 를 기다 리 는 것 을 막 습 니 다...
메 인 스 레 드 신호 방출...
t 스 레 드 DoWork 방법 으로 main 스 레 드 신 호 를 가 져 와 계속 실행...
ManualResetEvent
ManualResetEvent
과 AutoResetEvent
의 용법 은 유사 하 다.AutoResetEvent
은 Set
방법 을 호출 한 후에 신 호 를 방출(종료)에서 차단(비 종료)으로 자동 으로 바 꾸 고 한 번 에 한 스 레 드 만 신 호 를 받 을 수 있 습 니 다.한편,ManualResetEvent
은 Set
방법 을 호출 한 후에 자동 으로 신 호 를 방출(종료)에서 차단(종료 되 지 않 음)으로 바 꾸 지 않 고 신 호 를 계속 방출 하여 한 번 에 여러 개의 차단 스 레 드 가 운행 되 고 Reset
방법 만 수 동 으로 호출 하여 신 호 를 방출(종료)에서 차단(종료 되 지 않 음)으로 바 꿉 니 다.이후 Wait.One 방법 을 재 호출 해 야 스 레 드 가 다시 막 힐 수 있 습 니 다.
public class ThreadSafe
{
// ManualResetEvent
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main()
{
for(int i = 0; i <= 2; i++)
{
Thread t = new Thread(ThreadProc);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(500);
Console.WriteLine("
, , Set ");
mre.Set();
Thread.Sleep(500);
Console.WriteLine("
ManualResetEvent , Wait.One , 。");
for(int i = 3; i <= 4; i++)
{
Thread t = new Thread(ThreadProc);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(500);
Console.WriteLine("
Reset ,ManualResetEvent , Wait.One ");
mre.Reset();
Thread t5 = new Thread(ThreadProc);
t5.Name = "Thread_5";
t5.Start();
Thread.Sleep(500);
Console.WriteLine("
Set , ");
mre.Set();
}
private static void ThreadProc()
{
string name = Thread.CurrentThread.Name;
Console.WriteLine(name + " WaitOne()");
mre.WaitOne();
Console.WriteLine(name + " ");
}
}
//Thread_2 WaitOne()
//Thread_1 WaitOne()
//Thread_0 WaitOne()
// , , Set
//Thread_2
//Thread_1
//Thread_0
// ManualResetEvent , Wait.One , 。
//Thread_3 WaitOne()
//Thread_4 WaitOne()
//Thread_4
//Thread_3
/// Reset ,ManualResetEvent , Wait.One
//Thread_5 WaitOne()
// Set ,
//Thread_5
Interlocked하나의 변수 가 여러 스 레 드 로 수정 되면 읽 습 니 다.
Interlocked
사용 가능 합 니 다.컴퓨터 에 서 는 데이터 에 대한 첨삭 이 원자 적 이라는 것 을 보장 할 수 없다.왜냐하면 데이터 에 대한 조작 도 절차 적 이기 때문이다.
Interlocked
은 다 중 스 레 드 가 공유 하 는 변수 에 원자 조작 을 제공 합 니 다.Interlocked
은 원자 조작 이 필요 한 방법 을 제공 했다.value 첫 번 째 매개 변수 가 세 번 째 매개 변수 와 같다 면 value 를 첫 번 째 매개 변수 에 할당 합 니 다.
comparand 와 첫 번 째 매개 변 수 를 비교 합 니 다.
ReaderWriterLock
자원 이나 데 이 터 를 방문 하기 전에 최신 으로 확보 하려 면그러면
ReaderWriterLock
을 사용 할 수 있 습 니 다.이 자 물 쇠 는 자원 에 대한 할당 이나 업 데 이 트 를 가 져 올 때 자신 만 이 자원 에 접근 할 수 있 고 다른 스 레 드 에 접근 할 수 없습니다.자물쇠그러나 이 데 이 터 를 자물쇠 로 읽 을 때 열 쇠 를 실현 할 수 없습니다.lock
은 같은 시간 에 하나의 스 레 드 만 실행 할 수 있 습 니 다.한편,ReaderWriterLock
은 같은 시간 에 여러 개의 스 레 드 가 읽 기 동작 을 수행 할 수 있 거나 잠 겨 있 는 스 레 드 만 쓰기 동작 을 수행 할 수 있 습 니 다.
class Program
{
//
public static ReaderWriterLock readerwritelock = new ReaderWriterLock();
static void Main(string[] args)
{
//
Thread t1 = new Thread(Write);
// t1.Start(1);
Thread t2 = new Thread(Write);
//t2.Start(2);
// 10
for (int i = 3; i < 6; i++)
{
Thread t = new Thread(Read);
// t.Start(i);
}
Console.Read();
}
//
public static void Write(object i)
{
// ,20 。
Console.WriteLine(" :" + i + " ...");
readerwritelock.AcquireWriterLock(Timeout.Infinite);
Console.WriteLine(" :" + i + " " + DateTime.Now);
//
Console.WriteLine(" :" + i + " ...");
Thread.Sleep(1000);
readerwritelock.ReleaseWriterLock();
}
//
public static void Read(object i)
{
Console.WriteLine(" :" + i + " ...");
// ,20
readerwritelock.AcquireReaderLock(Timeout.Infinite);
Console.WriteLine(" :" + i + " " + DateTime.Now);
//
Console.WriteLine(" :" + i + " ...");
Thread.Sleep(1000);
readerwritelock.ReleaseReaderLock();
}
}
// writer reader 。 writer 。 reader 。
// reader
// :1 ...
// :1 2017/7/5 17:50:01
// :1 ...
// :2 ...
// :2 2017/7/5 17:50:02
// :2 ...
// writer
// :3 ...
// :5 ...
// :4 ...
// :5 2017/7/5 17:50:54
// :5 ...
// :3 2017/7/5 17:50:54
// :3 ...
// :4 2017/7/5 17:50:54
// :4 ...
참고:이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.