zoukankan      html  css  js  c++  java
  • 了解多线程临界区

    什么是临界区?

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

    代码:

    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)
            {
               //代码如上......
            }
            
        }
    

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

  • 相关阅读:
    42. Trapping Rain Water
    223. Rectangle Area
    645. Set Mismatch
    541. Reverse String II
    675. Cut Off Trees for Golf Event
    安装 VsCode 插件安装以及配置
    向上取整 向下取整 四舍五入 产生100以内随机数
    JS 判断是否为数字 数字型特殊值
    移动端初始配置,兼容不同浏览器的渲染内核
    Flex移动布局中单行和双行布局的区别以及使用
  • 原文地址:https://www.cnblogs.com/lilin/p/1719872.html
Copyright © 2011-2022 走看看