【多线程-线程同步】

线程同步:协调多个线程间的并发操作,以获得符合预期的,确定的执行结果,消除多线程应用程序的不确定性.

使用线程的同步:可以保护资源同时只能由一个线程访问,一般采取的措施是获取锁,释放锁。即锁机制;可以协调线程的访问顺序,即某一资源只能先由线程A访问,再由线程B进行访问。

    class Program
    {
        private static Thread subthread ;
        private static int i;
        static void Main(string[] args)
        {
            subthread = new Thread(new ThreadStart(GetShow));
            subthread.Start();   //开启线程
            GetShow();
            //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束");
        }
        static void GetShow()
        {
            Console.WriteLine(i);
            i++;
            //Console.WriteLine(i);
        }
    }

上面的代码执行时候,出现了两个线程同时访问同一个资源,向控制台输出后去执行i++操作,这样两个线程进来那一时间,i的值没有发生改变依旧是0,但执行i++后的值发生了改变,注释掉下面的输出运行程序发现:先输出2后输出的是1,这也是线程的执行顺序不确定而造成的值的输出顺序有差异。

使用排他锁,通过Monitor进行资源保护

1.使用对象作为锁对象:

 class Program
    {
        private static Thread subthread ;
        private static int i;
        private static object obj = new object();
        static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "主";
            subthread = new Thread(new ThreadStart(GetShow));
            subthread.Name = "subject";
            subthread.Start();   //开启线程
            GetShow();
            //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束");
        }
        static void GetShow()
        {
            Monitor.Enter(obj);// 在指定对象上获取排他锁。
            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
            i++;
            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
            Monitor.Exit(obj); // 释放指定对象上的排他锁。
        }
    }

使用System.Type进行锁对象:

修改上面的方法:运行结果与上面一致。

 <span style="white-space:pre">	</span>static void GetShow()
        {
            Monitor.Enter(typeof(Program));// 在指定对象上获取排他锁。
            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
            i++;
            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
            Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。
        }

使用lock加锁:

如果上面的Monitor.Exit(typeof(Program))前面代码出现异常的话,主线程在执行到异常出会抛出异常,可以通过:try catch finall进行处理:

            try
            {
                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
                i++;
                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
                throw new Exception("asdasd");
            }
            catch
            {

            }
            finally
            {
                Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。
            }

使用lock可以进行简化:实现效果和上面一样.

            lock (typeof(Program))
            {
                try
                {
                    Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
                    i++;
                    Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
                    throw new Exception("asdasd");
                }
                catch { }
            }

进行[MethodImpl(MethodImplOptions.Synchronized)]标记

创建线程的安全类型,可以使用[MethodImpl(MethodImplOptions.Synchronized)]进行标记:

        [MethodImpl(MethodImplOptions.Synchronized)]//进行标记
        static void GetShow()
        {
            try
            {
                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
                i++;
                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
                throw new Exception("asdasd");
            }
            catch { }
        }

使用Monitor协调线程的执行顺序:

    class Program
    {
        private static Thread subthread ;
        static void Main(string[] args)
        {
            Program p=new Program ();
            Thread.CurrentThread.Name = "主线程";
            subthread = new Thread(new ThreadStart(p.GetShow));
            subthread.Name = "子线程";
            subthread.Start();   //开启线程
            lock (typeof(Program))
            {
                Monitor.Wait(typeof(Program));   // 释放对象上的锁并阻止当前线程,直到它重新获取该锁。
                Console.WriteLine(Thread.CurrentThread.Name + "开始执行其他逻辑");
            }
        }

        void GetShow()
        {
            lock (typeof(Program))
            {
                Console.WriteLine(subthread.Name+"线程执行完毕");
                Monitor.Pulse(typeof(Program));  //通知等待队列中的线程锁定对象状态的更改。
            }
        }
    }

时间: 2024-10-18 08:35:17

【多线程-线程同步】的相关文章

多线程&线程同步

线程 程序执行过程中,并发执行的代码段. 线程之间可以共享内存. 线程安全 增加了同步处理,确保在同一时刻,只有一个线程执行同步代码. 保证线程安全的方法就是锁机制 java中的任何对象都可以作为锁对象 synchronized(lock){....} 代码块中的代码被确保同一时间只有一个线程才能执行 同步方法是用当前对象作为同步对象(this) public synchronized int getTicket(){...} synchronized关键字也能加在方法上 确保同一时间只有一个线

多线程——线程同步,死锁

线程同步: 为什么需要同步 ①   线程同步是为了防止多个线程访问一个数据对象时,对数据造成破坏. ②   线程的同步是保证多线程安全访问竞争资源的一种手段. 同步和锁 ①   Java中每一个对象都有一个内置锁. ②   当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁:当程序运行到synchronized同步代码块时,自动获得锁定对象的锁. ③   获得一个对象的锁也称为获取锁.锁定对象.在对象上锁定或在对象上同步.当程序运

Java多线程 线程同步

如果你正在写一个变量,它可能接下来将被另一个线程读取,或者正在读取一个上一次已经被另一个线程写过的变量,那么你需要使用同步,并且,读写线程都必须用相同的监视器锁同步.--Brain同步规则 synchronized 所有对象都自动含有单一的锁,当在调用一个对象的任意synchronized方法时,此对象将被加锁. 对于某个特定对象来说,所有的synchronized方法共享同一个锁.所以某个线程在访问对象的一个synchronized方法时,其他线程访问该对象的任何synchronized方法都

Java多线程——线程同步

在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系.可是有的时候,可能存在多个线程多同一个数据进行操作,这样,可能就会引用各种奇怪的问题.现在就来学习多线程对数据访问的控制吧. 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问.   一.多线程引起的数据访问安全问题 下面看一个经典的问题,银行取钱的问题: 1).你有一张银行卡,里面有50

JAVA多线程线程同步问题

线程同步 在多线程的编程环境下,可能看着没有问题的代码在运行几千上万或者更多次后,出现了一些看着很奇怪的问题,出现这样的问题的原因就是可能会有两个或者更多个线程进入了同一块业务处理代码中导致了判断失效.为了解决这个问题,JAVA引入了同步监视器来解决这个问题.同步监视器的通用方法就是同步代码块,也就是给一块代码加了同步锁. package cn.test.hf; import java.math.BigDecimal; /** * 模拟取钱操作 */public class RunnableTe

9 C++ Boost 多线程,线程同步

线程的创建 boost_thread,boost_system 多线程的创建 线程的参数传递 线程的创建方式 线程的join 加入join,回收线程 线程中断 线程中断2, 线程组 boost 线程的死锁 boost 线程递归锁 线程互斥锁,线程同步 unique_lock 锁,离开作用域自动释放 unique_lock 锁 示例 2,可以显式的释放锁 boost 1次初始化 boost 条件变量 boost 线程锁,一个账户往另外一个账户转钱案例 boost upgrade_lock 知识背景

第18章 多线程----线程同步

Java提供了线程同步的机制来防止资源访问的冲突. 1.线程安全 实际开发中,使用多线程程序的情况很多,如银行排号系统.火车站售票系统等.这种多线程的程序通常会发生问题. 以火车站售票系统为例,在代码中判断当前票数是否大于0,如果大于0则执行将该票出售给乘客功能,但当两个线程同时访问这段代码时(假如这时只剩下一张票),第一个线程将票售出,与此同时第二个线程也已经执行完成判断是否有票的操作,并得出结论票数大于0,于是它也执行售出操作,这样就会产生负数.所以在编写多线程程序时,应该考虑到线程安全问题

服务总结 -多线程 - 线程同步(AutoResetEvent与ManualResetEvent)

前言 在我们编写多线程程序时,会遇到这样一个问题:在一个线程处理的过程中,需要等待另一个线程处理的结果才能继续往下执行.比如:有两个线程,一个用来接收Socket数据,另一个用来处理Socket数据,而处理Socket数据的那个线程需要在接收到Socket数据后才能处理运行,就要等待接收线程接收数据.那么处理线程如何等待,接收线程又如何通知处理线程呢? 其中一个比较好的方式就是使用AutoResetEvent/ManualResetEvent 1. AutoResetEvent/ManualRe

多线程 - 线程同步锁(lock、Monitor)

1. 前言 多线程编程的时候,我们不光希望两个线程间能够实现逻辑上的先后顺序运行,还希望两个不相关的线程在访问同一个资源的时候,同时只能有一个线程对资源进行操作,否则就会出现无法预知的结果. 比如,有两个线程需要对同一个计数器加1,我们希望结果是计数器最终加2,但可能同时获取到了这个计数器,第一个线程对计数器加1,但第二个线程并不知道,于是重新对计数器加1,导致最终计数器损失了一个计数.为了解决这个问题,就必须在获取该计数器前锁定,防止其他线程再次获取,直到处理完成后再释放. Monitor.l