代码改变世界

C# 线程手册 第三章 使用线程 .NET 对同步的支持

2012-01-30 07:24  DanielWise  阅读(3306)  评论(4编辑  收藏  举报

.NET Framework 提供了很多System.Threading,System.EnterpriseService 和 System.Runtime.Compiler 命名空间中的很多类来帮助程序员开发线程安全代码。下表简要地描述了.NET Framework 中的一些同步类。

2012-1-30 8-38-00


MethodImplAttribute 类

正如System.Runtime.CompilerServices 命名空间名字所显式的,这个命名空间中包含影响CLR 运行时行为的属性。MethodImplAttribute是通知CLR某个方法是如何实现的众多属性之一。MethodImplAttribute 构造函数之一以MethodImplOptions作为参数。MethodImplOptions枚举有一个保证在任意时间仅有一个线程访问方法的同步字段名。这类似于我们在之前例子中用的lock 关键字。下面的MI.cs 显示了你可以怎样使用这个属性来同步一个方法:

/*************************************
/* Copyright (c) 2012 Daniel Dong
 * 
 * Author:oDaniel Dong
 * Blog:o  www.cnblogs.com/danielWise
 * Email:o guofoo@163.com
 * 
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.CompilerServices;

namespace MethodImpl
{
    class MI
    {
        //This attribute locks the method for use
        //by one and only one thread at a time.
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void doSomeWorkSync()
        {
            Console.WriteLine("doSomeWorkSync()" 
                + "--Lock held by Thread " 
                + Thread.CurrentThread.GetHashCode());

            //When a thread sleeps, it still holds the lock
            Thread.Sleep(5000);
            Console.WriteLine("doSomeWorkSync()"
                + "--Lock released by Thread "
                + Thread.CurrentThread.GetHashCode());
        }

        //This is a non synchronized method
        public void doSomeWorkNoSync()
        {
            Console.WriteLine("doSomeWorkNoSync()"
                + "--Entered Thread is "
                + Thread.CurrentThread.GetHashCode());
            Thread.Sleep(5000);
            Console.WriteLine("doSomeWorkNoSync()"
                + "--Leaving Thread is "
                + Thread.CurrentThread.GetHashCode());
        }

        static void Main(string[] args)
        {
            MI m = new MI();

            //Delegate for Non-Synchronous operation
            ThreadStart tsNoSyncDelegate =
                new ThreadStart(m.doSomeWorkNoSync);

            //Delegate for Synchronous operation
            ThreadStart tsSyncDelegate =
                new ThreadStart(m.doSomeWorkSync);

            Thread t1 = new Thread(tsNoSyncDelegate);
            Thread t2 = new Thread(tsNoSyncDelegate);

            t1.Start();
            t2.Start();

            Thread t3 = new Thread(tsSyncDelegate);
            Thread t4 = new Thread(tsSyncDelegate);

            t3.Start();
            t4.Start();

            Console.ReadLine();
        }
    }
}

输出结果类似以下(不同计算机的输出结果可能非常不同):

2012-1-30 8-59-09

在上面代码片段中,MI 类有两个方法:doSomeWorkSync() 和 doSomeWorkNoSync() 。MethodImpl 属性被应用到doSomeWorkSync() 方法上来同步它,而doSomeWorkNoSync() 方法未作改动,仍然可以在同一时间被多个线程访问。在Main() 方法中,线程t1 和 t2 访问非同步访问,线程t3 和 t4访问不同方法。使用Thread.Sleep() 方法来保证当一个线程仍然在方法中时另外一个竞争方法可以进入同一个方法。程序的期待行为时线程t1 和 t2 可以同时进入doSomeWorkNoSync()方法, 而仅允许一个线程(t3或t4)进入doSomeWorkSync()方法。如果t1 和 t2 线程优先级一样,那么线程的执行顺序将会是随机的;.NET Framework 不保证线程执行顺序。

如果你仔细看看输出结果,你将发现线程2(t1)和线程3(t2)在同一时间进入doSomeWorkNoSync() 方法,而一旦线程4(t3)在方法doSomeWorkSync()上获得锁的话,线程5(t4)就不允许进入这个方法直到线程4在这个方法上释放锁。

 

下一篇介绍.NET 同步策略…