多线程同步之——monitor

线程的同步有多种方法,这里简单学习一下使用monitor这个对象同步线程。

我们知道如果程序中有些操作比较耗时,那么就可以指派专门的线程来处理这件事,有时候,启动的多个线程需要同时执行一个方法、修改同一个变量等,那么这时候如何做好线程同步,就很关键。

程序实现的效果是:

两个线程删除同一个数组中的数据,删除完成后自动关闭线程。使用monitor对象实现。

程序实现的主要思路:

1、定义一个共同执行的方法——Run执行删除数组的元素,在这个方法中使用monitor对象同步线程。

如果有一个线程正在执行该方法,那么就将该方法保持一个种锁定的方法,其他的线程就只能等待,很多说法把monitor对象比作是一个出租车,如果有人已经打了这辆车,那么其他的人就不能再上,只能等待里面的人下车后才有机会上车。

         /// <summary>
        /// 共同执行的删除数组的元素的方法
        /// </summary>
        public void Run()
        {
            //记录要删除的数据
            string stringValue = null;
            #region 使用monitor对象同步线程
            //***********************************使用monitor对象同步线程*********************************************//
            //如果已经被某个线程锁定
            //使用线程锁住
            while (true)
            {
                Monitor.Enter(this);
                stringValue = (string)stringList[0];
                Console.WriteLine(Thread.CurrentThread.Name+"删除了"+stringValue );
                stringList.RemoveAt(0);

                //如果数组中的所有元素都已经被删除,那么就自动关闭线程
                if (stringList.Count==0)
                {
                    //执行关闭线程的事件,调用委托的方法
                    OnNumberClear(this, new EventArgs());
                    
                    
                }
                Monitor.Exit(this );
                Thread.Sleep(5);
            }

            //***********************************使用monitor对象同步线程*********************************************//
            #endregion
        }


 

2、定义一个事件,和关闭线程的方法,并将该方法委托给该事件,当数组元素删除完成后,自动调用该事件,然后执行关闭线程的方法。

 

        //数据删除完成后引发的事件(事件也是一种委托)
        private   event EventHandler OnNumberClear;

        //关闭线程的方法,要委托给自定义的事件
        /// <summary>
        /// 执行完成之后,停止所有线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ThreadDemo_OnNumberClear(object sender,EventArgs e )
        {
            Console.WriteLine("执行完成,停止所有线程。");
            thredOne.Abort();
            threadTwo.Abort();
            
        
        }


3、 在类的构造函数中初始化两个线程、要删除的数组、指定要执行的方法和委托给自定义事件的方法。

        /// <summary>
        /// 类的构造函数中将线程和数组对象以及完成后要执行的委托方法都构造好
        /// </summary>
        /// <param name="number">生成数组的元素个数</param>
        public ThreadDemo(int number)
        {
            //生成字串数组
            Random random = new Random(1000000);
            stringList = new ArrayList(number);
            for (int n = 0; n < number; n++)
            {
                stringList.Add(random.Next().ToString());
            }
            //初始化线程,指明相应的线程要做什么
            thredOne = new Thread( new ThreadStart(Run));
            threadTwo = new Thread(new ThreadStart(Run));

            //给线程起名字
            thredOne.Name = "线程1";
            threadTwo.Name = "线程2";

            //将关闭线程的方法委托给自定的事件
            //数据删除完成后,引发OnNumberClear事件;该事件将触发ThreadDemo_OnNumberClear方法执行
            //将ThreadDemo_OnNumberClear方法委托到OnNumberClear事件中去执行
            OnNumberClear += new EventHandler(ThreadDemo_OnNumberClear);


        }


 

4、其他的部分就不做解释,下面是所有的代码:

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


namespace DelArrayThreadExcise
{

    //这个程序的思路是共同做一件事情(从一个ArrayList中删除元素),如果执行完成了,两个线程都停止执行。
    //所有的工作都在一个类中实现

    //******************************实现两个线程删除一个数组中的元素********************************************
    //构造函数中:定义两个线程;生成数组
    //共同执行的删除的方法
    //定义一个启动多线程的方法
    //如果所有的数据都删除后就,自动终止线程,使用委托实现   
    
    class ThreadDemo
    {
        //定义线程和数组对象
        private Thread thredOne;
        private Thread threadTwo;
        private ArrayList stringList;

        //数据删除完成后引发的事件(事件也是一种委托)
        private   event EventHandler OnNumberClear;

        /// <summary>
        /// 类的构造函数中将线程和数组对象以及完成后要执行的委托方法都构造好
        /// </summary>
        /// <param name="number">生成数组的元素个数</param>
        public ThreadDemo(int number)
        {
            //生成字串数组
            Random random = new Random(1000000);
            stringList = new ArrayList(number);
            for (int n = 0; n < number; n++)
            {
                stringList.Add(random.Next().ToString());
            }
            //初始化线程,指明相应的线程要做什么
            thredOne = new Thread( new ThreadStart(Run));
            threadTwo = new Thread(new ThreadStart(Run));

            //给线程起名字
            thredOne.Name = "线程1";
            threadTwo.Name = "线程2";

            //将关闭线程的方法委托给自定的事件
            //数据删除完成后,引发OnNumberClear事件;该事件将触发ThreadDemo_OnNumberClear方法执行
            //将ThreadDemo_OnNumberClear方法委托到OnNumberClear事件中去执行
            OnNumberClear += new EventHandler(ThreadDemo_OnNumberClear);


        }

         /// <summary>
        /// 共同执行的删除数组的元素的方法
        /// </summary>
        public void Run()
        {
            //记录要删除的数据
            string stringValue = null;
            #region 使用monitor对象同步线程
            //***********************************使用monitor对象同步线程*********************************************//
            //如果已经被某个线程锁定
            //使用线程锁住
            while (true)
            {
                Monitor.Enter(this);
                stringValue = (string)stringList[0];
                Console.WriteLine(Thread.CurrentThread.Name+"删除了"+stringValue );
                stringList.RemoveAt(0);

                //如果数组中的所有元素都已经被删除,那么就自动关闭线程
                if (stringList.Count==0)
                {
                    //执行关闭线程的事件,调用委托的方法
                    OnNumberClear(this, new EventArgs());
                    
                    
                }
                Monitor.Exit(this );
                Thread.Sleep(5);
            }

            //***********************************使用monitor对象同步线程*********************************************//
            #endregion
        }
        
        //开启线程的方法
        public void Action()
        {
            thredOne.Start();
            threadTwo.Start();
        }

        //关闭线程的方法,要委托给自定义的事件
        /// <summary>
        /// 执行完成之后,停止所有线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ThreadDemo_OnNumberClear(object sender,EventArgs e )
        {
            Console.WriteLine("执行完成,停止所有线程。");
            thredOne.Abort();
            threadTwo.Abort();
            
        
        }

        static void Main(string[] args)
        {
            ThreadDemo demo = new ThreadDemo(1000);
            demo.Action();


        }
    }
}


 

5、总结:

1.上面使用了monitor对象同步线程,当一个线程使用monitor对象的Enter方法执行某段代码后,Exit方法前,其他的线程就没有机会在这个时刻,执行这些代码。

2.自定义事件也是一种委托,对事件的声名其实就是声明一个私有的委托变量。

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Rust是一种现代的系统级编程语言,它提供了内存安全、并发性和高性能的特性。在Rust中,多线程同步是通过标准库中的原子类型和同步原语来实现的。 Rust的原子类型(Atomic Types)是一种特殊的数据类型,可以在多个线程之间进行原子操作,保证操作的原子性。常见的原子类型包括AtomicBool、AtomicIsize、AtomicUsize等。通过原子类型,可以实现多线程之间的共享数据的安全访问。 除了原子类型,Rust还提供了一些同步原语,用于实现多线程之间的同步和互斥。其中最常用的是Mutex和RwLock。Mutex提供了互斥锁机制,确保在同一时间只有一个线程可以访问被锁定的数据。RwLock则提供了读写锁机制,允许多个线程同时读取数据,但只允许一个线程进行写操作。 使用Rust进行多线程同步的一般步骤如下: 1. 导入所需的库:在Rust中,需要使用std::sync模块中的相关类型和函数来实现多线程同步。 2. 创建共享数据:定义需要在多个线程之间共享的数据结构。 3. 使用原子类型:对需要在多个线程之间进行原子操作的数据使用原子类型进行封装。 4. 使用同步原语:使用Mutex或RwLock对需要进行互斥访问的数据进行封装。 5. 创建线程:使用std::thread模块创建多个线程,并传递共享数据的引用给每个线程。 6. 进行同步操作:在每个线程中,使用Mutex的lock方法获取锁,并对共享数据进行操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值