【C#多线程】lock/Monitor/Interlocked

1.lock

lock 用于读一个引用类型进行加锁,同一时刻内只有一个线程能够访问此对象。lock 是Monitor的语法糖。

Lock 锁定的对象,应该是静态的引用类型(字符串除外)。

    class Program
    {
        private static object obj = new object();
        private static int sum = 0;
        static void Main(string[] args)
        {
 
            Thread thread1 = new Thread(Sum1);
            thread1.Start();
            Thread thread2 = new Thread(Sum2);
            thread2.Start();
            while (true)
            {
                Console.WriteLine($"{DateTime.Now.ToString()}:" + sum);
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
        }
 
        public static void Sum1()
        {
            sum = 0;
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    sum += i;
                    Console.WriteLine("Sum1");
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }
            }
        }
 
        public static void Sum2()
        {
            sum = 0;
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    sum += 1;
                    Console.WriteLine("Sum2");
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }
            }
        }
    }

类的内部还可以调用自身实例作为锁对象:

class A
{
	lock(this){}
}

当锁定时,其它线程必须等待锁中的线程执行完成并释放锁。但是这可能会给程序带来性能影响。
锁不太适合I/O场景,例如文件I/O,繁杂的计算或者操作比较持久的过程,会给程序带来很大的性能损失。

2. Monitor

Monotor 是一个静态类型。
image

  • Wait执行后,阻塞当前线程,进入等待队列,obj上的锁被释放。
Wait(Object);	//释放obj上的锁,当前线程进入等待队列(阻塞)
Wait(Object, Int32);	//释放obj上的锁,当前线程进入等待队列,并在一定时间后进入就绪队列
  • Pulse/PulseAll执行后,有一个/所有在等待队列中的线程将进入就绪队列。(队列先进先出,所以最先进入的线程将被移入就绪队列)
        private static object obj = new object();
        private static bool acquiredLock = false;
		
		public static void Test()
        {
            try
            {
                Monitor.Enter(obj, ref acquiredLock);
            }
            catch { }
            finally
            {
                if (acquiredLock)
                    Monitor.Exit(obj);
            }
        }

3.Interlocked

1.前言

轻量级同步,因为它仅对整形数据(即int类型,long也行)进行同步。为多个线程共同访问的变量提供原子操作,这个类是一个静态类 它提供了以线程安全的方式递增、递减、交换和读取值的方法。
效率高于lock,但只能解决简单的同步问题:自增、自减、加、读取、赋值

2.方法

https://blog.51cto.com/13713878410/1530358
这些方法都是线程安全的。
image

public static uint Exchange (ref uint location1, uint value);
//将value赋值给location1
//返回值:location1的原始值

public static float CompareExchange (ref float location1, float value, float comparand);
//location1与comparand比较,若相等,则将location1置value
//返回值location1的原始值
private void ExchangeValue4()
{
	//if value4=0, set value4=99
	Interlocked.CompareExchange(ref value4, 99,0);
}
posted @ 2023-05-15 15:08  徘徊彼岸花  阅读(164)  评论(0编辑  收藏  举报