C# 线程安全

多个线程对同一资源的争夺,有可能出现线程不安全的现象。用lock这种最简单的方式实现下。

直观的看下这种情况:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace ThreadSafetyDemo
{
    class Program
    {
        [STAThread]
        static void Main()
        {
            Thread.CurrentThread.Name = "====主线程====";
            Program prg = new Program();

            Thread newThread = new Thread(new ThreadStart(prg.DoSomeWork));
            newThread.Name = "**新线程:";
            newThread.IsBackground = true;
            newThread.Start(); // 开始新线程

            prg.DoSomeWork();  // 开始主线程

            Console.ReadKey();
        }
        // 放在外面作为成员变量,这样连个线程操纵的时候才能看出不一样。
        private int counter = 0;  

        private void DoSomeWork()
        {
            for (int i = 1; i < 11; i++) {
                counter += i;
                Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter);
            }
        }
    }
}

输出:

====主线程====1
====主线程====4
====主线程====7
====主线程====11
====主线程====16
====主线程====22
====主线程====29
**新线程:2
**新线程:39
**新线程:42
**新线程:46
**新线程:51
**新线程:57
**新线程:64
**新线程:72
**新线程:81
**新线程:91
====主线程====37
====主线程====100
====主线程====110

每次的结果其实都不一样,这就是线程的不安全,多个线程操纵了同意资源。

保证线程安全,加一个lock块。

private void DoSomeWork()
{
    lock (this) {
        for (int i = 1; i < 11; i++) {
            counter += i;
            Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter);
        }
    }
}

这样就没问题,保证只有一个线程调用。

更优雅的方式写法:

增加命名空间using System.Runtime.CompilerServices;。然后在函数前增加一个这样的标签就可以——[MethodImpl(MethodImplOptions.Synchronized)]


[MethodImpl(MethodImplOptions.Synchronized)]
private void DoSomeWork()
{
    for (int i = 1; i < 11; i++) {
        counter += i;
        Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter);
    }
}

这样子也可以,也是同样的效果。

上一篇:Python中 collections模块的详细用法介绍


下一篇:python中max使用key参数