首页 > 编程笔记 > C#笔记 阅读:17

什么是线程同步,C#线程同步简介(附带实例)

在实际开发中,使用多线程程序的情况有很多,如银行排号系统、火车站售票系统等。这种多线程的程序通常会发生问题。

以火车站售票系统为例,在代码中判断当前票数是否大于 0,如果大于 0,则执行把火车票出售给乘客的功能,但当两个线程同时访问这段代码时(假如这时只剩下一张票),第一个线程将票售出,与此同时,第二个线程已经执行,并完成判断是否有票的操作,得出结论票数大于 0,于是它也执行将票售出的操作,这样票数就会产生负数。

所以在编写多线程程序时,应该考虑到线程安全问题。实质上,线程安全问题来源于两个线程同时存取单一对象的数据。

例如,在项目中未考虑到线程安全问题的基础上,模拟火车站售票系统的功能,主要代码如下:
class Program
{
    int num = 10; //设置当前总票数
    void Ticket()
    {
        while (true) //设置无限循环
        {
            if (num > 0) //判断当前票数是否大于0
            {
                Thread.Sleep(100); //使当前线程休眠100毫秒
                //票数减1
                Console.WriteLine(Thread.CurrentThread.Name + "----票数" + num--);
            }
        }
    }
    static void Main(string[] args)
    {
        Program p = new Program(); //创建对象,以便调用对象方法
        //分别实例化4个线程,并设置名称
        Thread tA = new Thread(new ThreadStart(p.Ticket));
        tA.Name = "线程一";
        Thread tB = new Thread(new ThreadStart(p.Ticket));
        tB.Name = "线程二";
        Thread tC = new Thread(new ThreadStart(p.Ticket));
        tC.Name = "线程三";
        Thread tD = new Thread(new ThreadStart(p.Ticket));
        tD.Name = "线程四";
        tA.Start(); //分别启动线程
        tB.Start();
        tC.Start();
        tD.Start();
        Console.ReadLine();
    }
}
运行结果为:
线程一-----票数10
线程三-----票数8
线程二-----票数7
线程四-----票数9
线程一-----票数6
线程二-----票数5
线程三-----票数4
线程四-----票数3
线程一-----票数1
线程三-----票数2
线程二-----票数0
线程四-----票数-1
从结果中可以看出,最后打印后剩下的票为负值,这样就出现了问题。

由于同时创建了 4 个线程,这 4 个线程同时执行,在 num 变量为 1 时,线程一、线程二、线程三、线程四都对 num 变量有存储功能,当线程一执行时,还没有来得及做递减操作,就指定它调用 Sleep() 方法进入就绪状态,这时线程二、线程三和线程四也都开始执行,发现 num 变量依然大于 0,但此时线程一休眠时间已到,将 num 变量值递减,同时线程二、线程三、线程四也都对 num 变量进行递减操操作,从而产生了负值。

那么该如何解决资源共享的问题呢?基本上所有解决多线程资源冲突问题的方法都采用给定时间只允许一个线程访问共享资源,这时就需要给共享资源上一道锁。这就好比一个人上洗手间时,他进入洗手间后会将门锁上,出来时再将锁打开,然后其他人才可以进入。这就是程序开发中的线程同步。

线程同步是指并发线程高效、有序地访问共享资源所采用的技术。所谓同步,是指某一时刻只有一个线程可以访问资源,只有当资源所有者自动放弃了代码或资源的所有权时,其他线程才可以使用这些资源。

相关文章