VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • C#教程之C# 多线程系列(一)(2)

  CLR给每个线程分配自己内存栈,因此局部变量可以保持分离。所以两次调用threadOne都正常打印了10个"t"。

3. 数据共享

复制代码
    class Program
    {
        static bool bDone = false;
        static void Main(string[] args)
        {
            Thread thread = new Thread(threadOne);
            thread.Start();
            threadOne();
            Console.ReadKey();
        }

        static void threadOne()
        {
            if(!bDone)
            {
                bDone = true;
                lib.put("threadOne");
            }
        }
    }
复制代码

 

如果多个线程对同一个对象实例有相同的引用,这些线程就共享这个对象实例的数据。所以只会输出一个threadOne。

4.线程安全

上述例子,是有可能打印出两次threadOne的。当bDone被置成true之前,若主线程和子线程都已经通过if判定,将打印两次。

 

复制代码
static void threadOne()
{
    if(!bDone)
    {
        Thread.Sleep(50);//加上sleep后,会出现主线程和子线程都通过if判定后才把bDone置成true,所以打印两次threadOne,
     bDone = true; 
     lib.put("threadOne"); 
  } 
}
复制代码

 

改进方式当读\写一个公共字段时,获取一个独占锁(exclusive lock)。C#提供了关键字lock

复制代码
class Program
    {
        static bool bDone = false;
        static readonly object locker = new object();
        static void Main(string[] args)
        {
            Thread thread = new Thread(threadOne);
            thread.Start();
            threadOne();
            Console.ReadKey();
        }

        static void threadOne()
        {
            lock (locker)
            {
                if (!bDone)
                {
                    Thread.Sleep(50);
                    bDone = true;
                    lib.put("threadOne");
                }
            }
        }
    }
复制代码

 

当两个线程同时抢占一个锁时(在这个例子中,locker,一个线程等待,或者阻塞,直到这个锁释放。在这个例子中,这个锁保证一次只有一个线程可以进入代码的临界区域,然后“threadOne”只会被打印一次。代码在这种不确定的多线程背景下中被保护被叫做线程安全。

lock关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。在块的开始处调用 Enter,而在块的结尾处调用 Exit。这样可确保当一个线程位于代码的关键部分时,另一个线程不会进入该关键部分。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。一个线程,当阻塞的时候,不占用CPU资源。

 5.Join和Sleep

Join是一种同步方法,阻止调用线程 (即,调用的方法的线程),直到线程其Join方法调用已完成。 使用此方法以确保线程已终止。 如果线程不会终止,调用方将无限期阻止。

Join有多个重载方法,可以在Join方法中添加一个参数,milliseconds或者timeSpan。如果这个线程结束了则Join方法返回true,如果这个线程超时则返回false,但不结束该线程。

复制代码
static void Main(string[] args)
{
    Thread thread = new Thread(threadOne);
    thread.Start();
    thread.Join();//等到thread线程结束后继续本线程
    lib.print("end");
    Console.ReadKey();
}

static void threadOne()
{
    lib.print("threadOne");
    Thread.Sleep(3000);
}
复制代码

 

Sleep暂停当前线程一段指定的时间。

Thread.Sleep(TimeSpan.FromHours(1));//sleep一个小时

Thread.Sleep(500);//500 线程被阻塞的毫秒数。 指定零0以指示应挂起此线程以使其他等待线程能够执行。

当使用SleepJoin暂停线程时,这个线程是阻塞的,不消耗CPU资源。


相关教程
关于我们--广告服务--免责声明--本站帮助-友情链接--版权声明--联系我们       黑ICP备07002182号