并发编程中.net与java的一些对比

时间:2021-08-23 22:04:02

Java在并发编程中进行使用java.util.concurrent.atomic来处理一些轻量级变量 如AtomicInteger AtomicBoolean等

.Net中则使用Interlocked来实现类似功能

Java中使用object的wait和notify方法来实现线程间的写作

.Net中可以使用Semaphore(信号量)、mutex(互斥)、和EventWaitHandle来实现 但是Semaphore类的构造函数需要指定初始入口数和最大入口数

msdn:

mutex:当两个或多个线程需要同时访问共享的资源时,系统将需要使用同步机制来确保一次只有一个线程使用的资源。 Mutex 是一个同步基元,授予于只有一个线程对共享资源的独占访问权限。 如果一个线程获取互斥体,第二个想要获取该互斥体挂起线程,直到第一个线程释放此斥锁。当互斥体发出信号以指示不拥有时,waitone方法将返回true。反之当超过waitone方法中的等待时间后 waitone将返回false。拥有互斥锁的线程可以请求中的重复调用相同的互斥体 WaitOne 而不会阻止其执行。 但是,调用线程必须 ReleaseMutex 方法以释放互斥体的所属权相同次数。

        private static Mutex mut = new Mutex();
private const int numIterations = ;
private const int numThreads = ;
static void Main(string[] args)
{
for (int i = ; i < numThreads; ++i)
{
Thread newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i+);
newThread.Start();
}
} static void ThreadProc()
{
for (int i = ; i < numIterations; i++)
{
useResource();
}
} static void useResource()
{
Console.WriteLine("{0} is requesting the mutex", Thread.CurrentThread.Name);
if (mut.WaitOne())
{
Console.WriteLine("{0} has enter the protected area", Thread.CurrentThread.Name);
Thread.Sleep();
Console.WriteLine("{0} is leaving the protected area", Thread.CurrentThread.Name);
mut.ReleaseMutex();
Console.WriteLine("{0} is released the mutex", Thread.CurrentThread.Name);
}
else
{
Console.WriteLine("{0} will not acquire the mutex", Thread.CurrentThread.Name);
}
}

运行结果:

Thread1 is requesting the mutex
Thread1 has enter the protected area
Thread2 is requesting the mutex
Thread3 is requesting the mutex
Thread1 is leaving the protected area
Thread1 is released the mutex
Thread3 has enter the protected area
Thread3 is leaving the protected area
Thread3 is released the mutex
Thread2 has enter the protected area
Thread2 is leaving the protected area
Thread2 is released the mutex

Semaphore:限制可同时访问某一资源或资源池的线程数。Semaphore分为本地信号量和系统信号量。本地信号量只能被所在进程内所有线程使用。系统信号量使用System.Threading.Semaphore.OpenExisting创建或打开

        private static Semaphore _pool;
private static int _padding;
static void Main(string[] args)
{
_pool = new Semaphore(, ); //初始化入口数和最大并发数
for (int i = ; i < ; ++i)
{
Thread newThread = new Thread(new ParameterizedThreadStart(Worker));
newThread.Start(i);
}
Thread.Sleep();
Console.WriteLine("main thread call release(3)");
_pool.Release(); Console.WriteLine("Main Thread exits"); } static void Worker(object obj)
{
Console.WriteLine("Thread {0} begins " + "and waits for the semaphore", obj);
_pool.WaitOne(); int padding = Interlocked.Add(ref _padding, );
Thread.Sleep( + padding); Console.WriteLine("Thread {0} releases the semaphore", obj);
Console.WriteLine("Thread {0} previous semaphore count: {1}",
obj, _pool.Release());
}

执行结果:

Thread 0 begins and waits for the semaphore
Thread 1 begins and waits for the semaphore
Thread 2 begins and waits for the semaphore
Thread 3 begins and waits for the semaphore
Thread 4 begins and waits for the semaphore
main thread call release(3)
Main Thread exits
Thread 3 releases the semaphore
Thread 3 previous semaphore count: 0
Thread 4 releases the semaphore
Thread 4 previous semaphore count: 0
Thread 0 releases the semaphore
Thread 0 previous semaphore count: 0
Thread 2 releases the semaphore
Thread 2 previous semaphore count: 1
Thread 1 releases the semaphore
Thread 1 previous semaphore count: 2

EventWaitHandle:EventWaitHandle 类允许线程通过发信号互相通信。通常,一个或多个线程在 EventWaitHandle 上阻止,直到一个未阻止的线程调用 Set 方法,以释放一个或多个被阻止的线程。

ManualResetAutoReset的区别:用 EventResetMode.AutoReset 标志创建的 EventWaitHandle 在终止时会自动重置。用 EventResetMode.ManualReset 标志创建的 EventWaitHandle 一直保持终止状态

        private static EventWaitHandle ewh;
private static long threadCount = ;
private static EventWaitHandle clearCount =
new EventWaitHandle(false, EventResetMode.AutoReset); static void Main(string[] args)
{
ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
for (int i = ; i <= ; i++)
{
Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
t.Start(i);
}
while (Interlocked.Read(ref threadCount) < )
{
Thread.Sleep();
}
while (Interlocked.Read(ref threadCount) > )
{
Console.WriteLine("Press ENTER to release a waiting thread.");
Console.ReadLine();
WaitHandle.SignalAndWait(ewh, clearCount);
}
Console.WriteLine();
ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
for (int i = ; i <= ; i++)
{
Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
t.Start(i);
}
while (Interlocked.Read(ref threadCount) < )
{
Thread.Sleep();
}
Console.WriteLine("Press ENTER to release the waiting threads.");
Console.ReadLine();
ewh.Set();
} public static void ThreadProc(Object num)
{
int index = (Int32)num;
Console.WriteLine("Thread{0} blocked", num);
Interlocked.Increment(ref threadCount);
ewh.WaitOne();
Console.WriteLine("Thread {0} exits.", num);
Interlocked.Decrement(ref threadCount);
clearCount.Set();
}

对比:

mutex类强制线程标示,只能由获得他的线程释放互斥体,而Semaphore并不强制线程标示,可以跨应用程序域边界传递互斥体