当前位置: 首页 > article >正文

c#中lock的经典示例

lock 是 C# 中的一种用于同步线程执行的机制,它帮助确保多个线程在访问共享资源时不会发生冲突或数据损坏。其作用是通过给临界区(即多线程访问共享资源的代码段)加锁,使得在同一时刻只能有一个线程进入执行该代码段。

1、lock 的工作原理

  • 加锁和解锁:当一个线程进入一个 lock 块时,它会获取一个对象的锁(通常是该块代码所属对象的锁)。其他线程在该锁被释放之前无法进入同一 lock 块。当线程退出 lock 块时,它会自动释放锁。
  • 防止线程冲突:lock 主要用于保护共享数据,避免多个线程同时访问或修改共享资源,造成数据不一致或程序崩溃的问题。

2、语法

lock (someObject)
{
    // 临界区代码:只有获得锁的线程能进入
    // 共享资源的操作代码
}

3、关键点

  1. someObject:lock 语句后面必须跟一个对象,这个对象用于在多个线程之间进行同步。通常使用类的实例对象,或是使用 this 来加锁当前对象。someObject 作为锁,通常不会使用原始类型数据或者是可变的对象。
  2. 自动解锁:一旦线程执行完 lock 块中的代码,锁就会自动释放,其他线程就有机会获取锁并进入临界区。
  3. 死锁:如果两个或多个线程相互等待对方释放锁,可能会导致死锁(即程序进入永久等待状态)。因此,设计时要注意锁的获取顺序和策略,避免这种情况。

4、lock 的实际应用

lock 经常用于以下场景:

  • 操作共享数据:当多个线程需要操作同一资源时,通过 lock 来确保只有一个线程能够访问该资源,从而避免数据竞争。
  • 数据库或文件访问:当多个线程需要访问数据库或文件时,需要同步这些访问操作,以防止数据损坏。

5、lock的经典示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace Demo
{
    class Program
    {
        int num = 10;//设置当前总票数
        void Ticket()
        {
            while (true)//设置无限循环
            {
                Console.WriteLine("  " + Thread.CurrentThread.Name + " lock前");//申请lock
                lock (this)//锁定代码块,以便线程同步
                {
                    Console.WriteLine("    " + Thread.CurrentThread.Name + " lock中");//获得lock
                    if (num > 0)//判断当前票数是否大于0
                    {
                        Console.WriteLine("    " + Thread.CurrentThread.Name + " Sleep(100)");
                        Thread.Sleep(100);//使当前线程休眠100毫秒
                        Console.WriteLine("    " + Thread.CurrentThread.Name + "----票数" + num--);//票数减1
                    }
                    else
                    {
                        Console.ReadLine();
                    }
                }
                Console.WriteLine("  " + Thread.CurrentThread.Name + " lock后");//释放lock
            }
        }
        static void Main(string[] args)
        {
            Program p = new Program();//创建对象,以便调用对象方法
            Thread tA = new Thread(new ThreadStart(p.Ticket));//分别实例化4个线程,并设置名称
            tA.Name = "线程A";
            Thread tB = new Thread(new ThreadStart(p.Ticket));
            tB.Name = "线程B";
            Thread tC = new Thread(new ThreadStart(p.Ticket));
            tC.Name = "线程C";
            Thread tD = new Thread(new ThreadStart(p.Ticket));
            tD.Name = "线程D";
            tA.Start(); //分别启动线程
            Console.WriteLine("tA.Start");
            tB.Start();
            Console.WriteLine("tB.Start");
            tC.Start();
            Console.WriteLine("tC.Start");
            tD.Start();
            Console.WriteLine("tD.Start");
            Console.ReadLine();
        }
    }
}

运行结果

tA.Start			    ->main中,线程A启动
  线程A lock前		    ->	进入线程A,线程A申请lock
    线程A lock中		->	    线程A获得lock
    线程A Sleep(100)	->		线程A休眠
tB.Start				->main中,线程B启动				 ->这里可以看到线程休眠程序,会返回main
  线程B lock前		    ->	进入线程B,线程B申请lock
tC.Start				->main中,线程C启动
  线程C lock前		    ->	进入线程C,线程C申请lock
tD.Start				->main中,线程D启动
  线程D lock前		    ->	进入线程D,线程D申请lock
    线程A----票数10		->		线程A休眠结束,线程A运行
  线程A lock后		    ->	线程A释放lock
  线程A lock前		    ->	线程A申请lock
    线程B lock中	    ->	    线程B获得lock
    线程B Sleep(100)	->		线程B休眠
    线程B----票数9		->		线程B休眠结束,线程B运行	->这里可以看到线程休眠,不会释放lock
  线程B lock后		    ->	线程B释放lock
  线程B lock前		    ->	线程B申请lock
    线程C lock中	    ->	    线程C获得lock
    线程C Sleep(100)	->		线程C休眠
    线程C----票数8		->		线程C休眠结束,线程C运行
  线程C lock后		    ->	线程C释放lock
  线程C lock前		    ->	线程C申请lock
    线程D lock中
    线程D Sleep(100)
    线程D----票数7
  线程D lock后
  线程D lock前
    线程A lock中
    线程A Sleep(100)
    线程A----票数6
  线程A lock后
  线程A lock前
    线程B lock中
    线程B Sleep(100)
    线程B----票数5
  线程B lock后
  线程B lock前
    线程C lock中
    线程C Sleep(100)
    线程C----票数4
  线程C lock后
  线程C lock前
    线程D lock中
    线程D Sleep(100)
    线程D----票数3
    线程A lock中
    线程A Sleep(100)
  线程D lock后
  线程D lock前
    线程A----票数2
  线程A lock后
  线程A lock前
    线程B lock中
    线程B Sleep(100)
    线程B----票数1
  线程B lock后
  线程B lock前
    线程C lock中

6、 死锁的经典示例

using System;
using System.Threading;
 
class Program
{
    private readonly object lock1 = new object();
    private readonly object lock2 = new object();
 
    public void Thread1()
    {
        lock (lock1)
        {
            Console.WriteLine("Thread 1: Acquired lock1");
            Thread.Sleep(1000);  // 模拟一些工作
            Console.WriteLine("Thread 1: Trying to acquire lock2");
            lock (lock2)
            {
                Console.WriteLine("Thread 1: Acquired lock2");
            }
        }
    }
 
    public void Thread2()
    {
        lock (lock2)
        {
            Console.WriteLine("Thread 2: Acquired lock2");
            Thread.Sleep(1000);  // 模拟一些工作
            Console.WriteLine("Thread 2: Trying to acquire lock1");
            lock (lock1)
            {
                Console.WriteLine("Thread 2: Acquired lock1");
            }
        }
    }
 
    static void Main(string[] args)
    {
        Program p = new Program();//创建对象,以便调用对象方法
 
        // 创建两个线程
        Thread t1 = new Thread(p.Thread1);
        Thread t2 = new Thread(p.Thread2);
 
        // 启动线程
        t1.Start();
        t2.Start();
 
        // 等待线程结束
        t1.Join();
        t2.Join();
    }
}

运行结果

Thread 1: Acquired lock1
Thread 2: Acquired lock2
Thread 1: Trying to acquire lock2
Thread 2: Trying to acquire lock1


http://www.kler.cn/a/537307.html

相关文章:

  • 青少年编程与数学 02-009 Django 5 Web 编程 01课题、概要
  • 2、k8s的cni网络插件和基本操作命令
  • 项目顺利交付,几个关键阶段
  • 2025.2.5——五、[网鼎杯 2020 青龙组]AreUSerialz 代码审计|反序列化
  • C++ 课程学习笔记:从对象生命周期看资源管理之道
  • RabbitMQ 从入门到精通:从工作模式到集群部署实战(三)
  • 计算机图形学基础WebGL引擎—粒子系统实现
  • 如何用python做一个小程序进行炒股?
  • Vue注意事项
  • Pygame介绍与游戏开发
  • 【设计模式】
  • Vue Router 底层工作原理解析
  • Github标星25K+超火的Android实战项目,Android篇_github android 和后台项目
  • 客户端与服务器端安全:两者有何不同?
  • 鼠标滚轮冒泡事件@wheel.stop
  • Git Command(待更新)
  • C# 综合运用介绍
  • base库学习
  • 绿虫光伏仿真设计软件基于Unity3D引擎的革命性突破
  • 植物大战僵尸融合版(电脑/安卓)
  • 大模型RAG优化之高可用向量数据库的“热更”难题与解决方案
  • quartus24.1版本子模块因时钟问题无法综合通过,FPGA过OOC问题复盘
  • 运行时数据区概述及线程
  • ubuntu的terminator设置自动补全
  • 【论文精读】《Towards Deep Learning Models Resistant to Adversarial Attacks》
  • [论文阅读] Knowledge Fusion of Large Language Models