C# lock 用法详解

作者:袖梨 2022-06-25

对某个文件进行读写操作,对于这些操作我们以前往往不能很好的进行处理,自从c#语言中引入了lock这个关键字,以上问题就比较容易予以解决了,下面就是一段简单的代码。

#include     
#include     
#include     

int   main(void)  
{  
      clock_t   start,   end;  
      start   =   clock();  

      delay(2000);  

      end   =   clock();  
      printf( "the   time   was:   %fn ",   (end   -   start)   /   clk_tck);  

      return   0;  
}


在做邮箱接收网关的时候遇到了以下的需求,要求为每一个邮箱开启一个接收线程,从pop3服务器上收取,然后将邮件存放到统一的ftp服务器上,要求邮件按收接顺充从1开始顺充编号。

我实现的方法为,为每个邮箱new出实例,然后分别赋给pop3邮箱地址,用户名,密码等参数。这里涉及到一个编号同步的问题,因为每个接收邮件的线程都是自己执行,所以取得编号并且递增这个动作是互斥的。

以一个静态变量表示编号如下

class emailinfo  {  public static int currentnumber;  }  
那在当前线程取得这个步骤为

_currentnumber=++emailinfo.currentnumber;

虽然此为一句,但在计算机运行时却分为多步,如下

emialinfo.currentnumber加1--emailinfo.currentnumber返回值给_currentnumber,也许线程1执行了emailinfo.currentnumber加1
的操作,但还没有取得返回值,此时线程2又执行了emailinfo.currentnumber加1的操作,然后又线程1,线程2取得了返回值就是一样的,这样就失去了按顺序递增的作用。

此时查找了网上有关线程同步的方法,其实用lock语句锁住递增的那一段即可。而介绍的相关用法为

lock(this)  {  _currentnumber=++emailinfo.currentnumber;  }  
本以为这样就可以成功,谁知道还是无效,反复查找才发现没弄清楚lock的用法。因为网上所讲的资料,举的例子比较简单,是直接new
出一个对像,然后为对像的一个函数创建了多个线程运行,所以它的同步只要lock住this即它自己就行了。因为此时只有一个实例在运,而我是new
出了多个对像,lock住每个自己的实例所以当然无效。

所以自然想了一个解决方法,就lock住相同的一个实例就行了。

因为我每个邮件接收线程的参数都是不同的,所以还是new出几个实像,但lock的方法改为如下

先为emailinfo加一个静态变量

class emailinfo  { 
public static object syncroot = new object();  public static int currentnumber;  }  然后lock改为  lock(emailinfo.syncroot)  {  _currentnumber=++emailinfo.currentnumber;  }  


c# lock同时访问共享数据

同时需要对某个数据进行操作,或者对某个文件进行读写操作,对于这些操作我们以前往往不能很好的进行处理,自从c#语言中引入了lock这个关键字,以上问题就比较容易予以解决了,下面就是一段简单的代码。

public class accesscontrol()
{
    private static object privateobjectlock = new object();

    public static accessresult()
    {
    lock(privateobjectlock)
    {
         //数据操作语句
    }
    }
}

下面个lock用法实例

using system;

namespace threadtest29
{
    class account
    {
        private object thislock = new object();
        int balance;
        random r = new random();

        public account(int initial)
        {
            balance = initial;
        }

        int withdraw(int amount)
        {
            if (balance < 0)
            {
                throw new exception("负的balance.");
            }
            //确保只有一个线程使用资源,一个进入临界状态,使用对象互斥锁,10个启动了的线程不能全部执行该方法
            lock (thislock)
            {
                if (balance >= amount)
                {
                    console.writeline("----------------------------:" + system.threading.thread.currentthread.name + "---------------");
                   
                    console.writeline("调用withdrawal之前的balance:" + balance);
                    console.writeline("把amount输入 withdrawal     :-" + amount);
                    //如果没有加对象互斥锁,则可能10个线程都执行下面的减法,加减法所耗时间片段非常小,可能多个线程同时执行,出现负数。
                    balance = balance - amount;
                    console.writeline("调用withdrawal之后的balance :" + balance);
                    return amount;
                }
                else
                {
                    //最终结果
                    return 0;
                }
            }
        }
        public void dotransactions()
        {
            for (int i = 0; i < 100; i++)
            {
                //生成balance的被减数amount的随机数
                withdraw(r.next(1, 100));
            }
        }
    }

    class test
    {
        static void main(string[] args)
        {
            //初始化10个线程
            system.threading.thread[] threads = new system.threading.thread[10];
            //把balance初始化设定为1000
            account acc = new account(1000);
            for (int i = 0; i < 10; i++)
            {
                system.threading.thread t = new system.threading.thread(new system.threading.threadstart(acc.dotransactions));
                threads[i] = t;
                threads[i].name = "thread" + i.tostring();
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].start();
            }
            console.readkey();
        }
    }
}

相关文章

精彩推荐