首页 > 代码库 > 线程系列01,前台线程,后台线程,线程同步

线程系列01,前台线程,后台线程,线程同步

在控制台应用程序集中,Main方法开始的是一个线程。如果要再创建线程,需要用到System.Threading这个命名空间。

 

□ 创建第一个线程

using System;
using System.Threading;
namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var thread = new Thread(DoSth);
            thread.Start();
        }
        static void DoSth()
        {
            Console.WriteLine("我来自另外一个线程");
        }
    }
}

 

□ 前台线程和后台线程

新建的线程在默认情况下是前台线程,可以通过把IsBackground属性设置为true,把线程定义为后台线程,一旦定义成后台线程,只要前台线程结束,无论后台线程是否结束,应用程序进程结束。

using System;
using System.Threading;
namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            var thread = new Thread(DoSth);
            thread.IsBackground = true;
            thread.Start(1);
            Console.WriteLine("离开主线程");
        }
        static void DoSth(object threadId)
        {
            Console.WriteLine("我来自另外一个线程" + threadId);
        }
    }
}

○ ManagedThreadId属性,托管线程Id,在进程内唯一,与操作系统的线程Id不是一回事。
○ Start方法可以带参数,参数将被传递到线程方法
○ IsBackground属性,设置线程是否为后台线程

 

□ 线程同步

※ 线程不同步的问题

假设主程序中有一个静态变量,在主程序的方法内无限循环,每次让该静态变量自增1。

如果把该方法交给一个线程。

    class Program
    {
        private static int count = 0;
        static void Main(string[] args)
        {
            var t1 = new Thread(AddCount);
            t1.Start();
        }
        static void AddCount()
        {
            while (true)
            {
                int temp = count;
                Thread.Sleep(1000);
                count = temp + 1;
                Console.WriteLine("我的托管线程ID为:" + Thread.CurrentThread.ManagedThreadId + " 目前count的值为:" + count);
                Thread.Sleep(1000);
            }
        }
    }

运行良好,显示的count值是连续递增1。

 

如果把该方法交给2个线程。

    class Program
    {
        private static int count = 0;
        static void Main(string[] args)
        {
            var t1 = new Thread(AddCount);
            var t2 = new Thread(AddCount);
            t1.Start();
            t2.Start();
        }
        ......
    }

我们发现,count的值不是递增。也就是说,count的值没有做到同步。

1

→进入线程1,temp=0,线程1开始sleep
→进入线程2,temp=0,线程2开始sleep
→线程1"醒来",让count=1,显示count值为1,又sleep
→线程2"醒来",temp还是为0,所以count还是为1,显示count值为1,又sleep
→如此循环
这里的问题是:本想让count一直递增,但线程1和线程2没有适时同步。如何解决呢?

 

※ 让线程同步

使用lock语句块,可以让2个线程同步,让每次只有一个线程进入程序执行的某个部分。

    class Program
    {
        private static int count = 0;
        static object o = new object();
        static void Main(string[] args)
        {
            var t1 = new Thread(AddCount);
            var t2 = new Thread(AddCount);
            t1.Start();
            t2.Start();
        }
        static void AddCount()
        {
            while (true)
            {
                lock (o)
                {
                    int temp = count;
                    Thread.Sleep(1000);
                    count = temp + 1;
                    Console.WriteLine("我的托管线程ID为:" + Thread.CurrentThread.ManagedThreadId + " 目前count的值为:" + count);
                }            
                Thread.Sleep(1000);
            }
        }
    }

2

 

总结:
○ 如果允许一个主线程结束,其它线程不管执行情况如何都结束,就把其它线程设置为后台线程。
○ lock语句块能保证线程同步

 

 

 

线程系列01,前台线程,后台线程,线程同步