您的位置:首页 > 编程语言 > C#

C#线程间同步的几种实现方式

2016-03-01 20:30 633 查看

一、使用信号量

using System;
using System.Threading;

namespace SemaphoreDemo
{
class Program
{
static void Main(string[] args)
{
for(int i = 0; i <= 6; i++)
{
string threadName = "thread " + i;
int secondsToWait = 2 + 2 * i;
var t = new Thread(() => AccessDatabase(threadName, secondsToWait));
t.Start();
}

Console.ReadKey();
}
//可同时有四个资源可访问
static SemaphoreSlim _semaphore = new SemaphoreSlim(4);

static void AccessDatabase(string name, int seconds)
{
Console.WriteLine("{0} waits to access a database", name);
_semaphore.Wait();
Console.WriteLine("{0} was granted an access to a database", name);

Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("{0} is completed", name);
_semaphore.Release();
}
}
}

二、使用AutoResetEvent

using System;
using System.Threading;

namespace AutoResetEventDemo
{
class Program
{
static void Main(string[] args)
{
var t = new Thread(() => Process(10));
t.Start();

Console.WriteLine("waiting for another thread to complete work");
_workerEvent.WaitOne();
Console.WriteLine("first operation is completed!");
Console.WriteLine("performing an operation on a main thread");
Thread.Sleep(TimeSpan.FromSeconds(5));
_mainEvent.Set();
Console.WriteLine("now running the second operation on a second thread");
_workerEvent.WaitOne();
Console.WriteLine("second operation is completed!");

Console.ReadKey();
}

private static AutoResetEvent _workerEvent = new AutoResetEvent(false);
private static AutoResetEvent _mainEvent = new AutoResetEvent(false);

static void Process(int seconds)
{
Console.WriteLine("starting a long running work...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("work is done!");
_workerEvent.Set();
Console.WriteLine("waiting for a main thread to complete its work");
_mainEvent.WaitOne();
Console.WriteLine("starting second operation...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("work is done!");
_workerEvent.Set();
}
}
}

三、使用ManualResetEvent

using System;
using System.Threading;

namespace ManualResetEventSlimDemo
{
class Program
{
static void Main(string[] args)
{
var t1 = new Thread(() => TravelThroughGates("thread 1", 5));
var t2 = new Thread(() => TravelThroughGates("thread 2", 5));
var t3 = new Thread(() => TravelThroughGates("thread 3", 5));
t1.Start();
t2.Start();
t3.Start();
Thread.Sleep(TimeSpan.FromSeconds(6));
Console.WriteLine("the gates are now open!");
_mainEvent.Set();
Thread.Sleep(TimeSpan.FromSeconds(2));
_mainEvent.Reset();
Console.WriteLine("the gates have been closed!");
Thread.Sleep(TimeSpan.FromSeconds(10));
Console.WriteLine("the gates are now open for the second time!");
_mainEvent.Set();
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("the gate have been closed!");
_mainEvent.Reset();

Console.ReadKey();
}

static ManualResetEventSlim _mainEvent = new ManualResetEventSlim(false);

static void TravelThroughGates(string threadName, int seconds)
{
Console.WriteLine("{0} fails to sleep", threadName);
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("{0} waits for the gates to open!", threadName);
_mainEvent.Wait();
Console.WriteLine("{0} enters the gates!", threadName);
}
}
}

四、使用CountDownEvent

using System;
using System.Threading;

namespace CountDownEventDemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting two operations");
var t1 = new Thread(() => PerformOperation("operation 1 is completed", 4));
var t2 = new Thread(() => PerformOperation("operation 2 is completed", 8));
t1.Start();
t2.Start();
//等待所有信号量返回
//如果没有Signal()返回,将永久性等待;或可使用带时间参数方式等待
_countdown.Wait();
Console.WriteLine("both operation have been completed");
_countdown.Dispose();

Console.ReadKey();
}
//计数为2
static CountdownEvent _countdown = new CountdownEvent(2);

static void PerformOperation(string message, int seconds)
{
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine(message);
//返回信号
_countdown.Signal();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: