• 了解多线程临界区


    什么是临界区?

    在任意时刻只允许一个线程对共享资源进行访问的区域,也就是多个线程同时访问同一个全局变量,如果都是读取操作,则不会出现问题。 如果一个线程负责改变此变量的值,而其他线程负责同时读取变量内容,则不能保证读取到的数据是经过写线程修改后的。为了确保读线程读取到的是经过修改的变量,就必须在向变量写入数据时禁止其他线程对其的任何访问,直至赋值过程结束后再解除对其他线程的访问限制。

    代码:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    
    class Lock
    {
        static readonly object lockObj = new object();
        int m = 1;
    
        public void Run()
        {
            if (m > 0)
            {
                Console.WriteLine(Thread.CurrentThread.Name + "已进入准备睡眠m值:" + m.ToString());
                Thread.Sleep(100);
                Console.WriteLine(Thread.CurrentThread.Name + "减之前m值:" + m.ToString());
                m = m - 1;
                Console.WriteLine(Thread.CurrentThread.Name + "减之后m值" + m.ToString());
                if (m < 0)
                {
                    Console.WriteLine("为负数!");
                }
                Console.WriteLine("-----------------");
            }
        }
    }
    
    class Test
    {
        private static Thread[] trray = new Thread[10];
    
        public static void Main()
        {
            Lock l = new Lock();
    
            for (int i = 0; i < 10; i++)
            {
                trray[i] = new Thread(new ThreadStart(l.Run));
            }
    
            for (int i = 0; i < 10; i++)
            {
                trray[i].Start();
                trray[i].Name = "线程:" + i.ToString(); ;
            }
            Console.ReadLine();
        }
    }

    运行结果

    上面的Run方法按逻辑,辅助线程不可能进入代码块if (m < 0)负数里,但看上图的运行结果,已经进入了.我是为什么呢?
    是这样的,首先全局变量m初始值为1,10个线程在运行if (m > 0)时都为True,所以都进入了代码块.Thread.Sleep(100);这名意思是等待10个线程都进入.某一线程执行m=m-1,运行后m值为0.这时注意因m为全局变量,所以这时第二个线程的m值为0,而不是初始值1.减之后就为-1了.

    如果想要下图正常的结果,加锁.

    public void Run()
        {
            lock (lockObj)
            {
                Console.WriteLine(Thread.CurrentThread.Name + "已进入lock里");
                if (m > 0)
                {
                    //代码如上......
                }
            }
        }
    

    如果变量m为局部变量,如下代码

    public void Run()
        {
            int m =1; 
            if (m > 0)
            {
               //代码如上......
            }
            
        }
    

    不存在多线程临界区,线程是安全的.运行结果如下:

  • 相关阅读:
    第二次结对作业
    软件工程第一次结对作业2
    软件工程第一次结对作业1<embed border="0" marginwidth="0" marginheight="0" width=330 height=86 src="/music.163.com/outchain/player?type=0&id=273848636&auto=1&height=66"></embed>
    第三次软件工程作业——两题
    第三次软件工程作业——最大连续子数组和(最大子段和)
    第三次软件工程作业——商场营销税额
    软件工程第二次作业
    软件工程第一次作业
    Markdown 使用说明(转CSDN)
    大坑!常被忽视又不得不注意的小细节——%I64,%lld与cout(转载)
  • 原文地址:https://www.cnblogs.com/lilin/p/1719872.html
Copyright © 2020-2023  润新知