C#学习笔记--线程争用条件与死锁

本文档只是自己的学习笔记,可能有误,如果有误请大家帮忙指出,谢谢。

争用条件

当多个线程同时对一个对象进行操作时,可能就会出现争用条件的情况,这么说可能大家没法理解,直接上例子

例:
先声明一个对象,其中有一个int值默认为5,还有一个ChangeId方法,在这个方法中,会先对nameId进行自增操作,再判断如果nameId为5的话,就输出“nameId等于5”。

class Class1
    {
        private int nameId = 5;

        public void ChangeId()
        {
            
            nameId++;
            if (nameId == 5)
            {
                Console.WriteLine("nameId等于5");
            }
            nameId = 5;
        }
        
    }

我想很多人看到这都时候都会想,在这个方法中肯定不可能输出nameID等于5的语句。那么我们再接着往下看

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

namespace 争用条件
{
    class Program
    {
        static void changeID(object o)
        {
            Class1 class1 = o as Class1;

            while (true)
            {
             
                    class1.ChangeId();
               
            }
        }

        static void Main(string[] args)
        {
            Class1 test = new Class1();//声明定义一个对象
            Thread thread = new Thread(changeID);//开启一个线程,在线程中传入changeID方法
            thread.Start(test);//开始线程
            //new Thread(changeID).Start(test);
        }
    }
}

结果:
在这里插入图片描述
可以看到,当只有一个线程访问的时候,对象的方法中是不可能输出 nameI等于5的语句,但是如果有两个线程同时访问的时候回发生怎么样的情况呢?话不多说,看案例

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

namespace 争用条件
{
    class Program
    {
        static void changeID(object o)
        {
            Class1 class1 = o as Class1;

            while (true)
            {
                
                    class1.ChangeId();
                
              
            }
           
        }

        static void Main(string[] args)
        {
            Class1 test = new Class1();
            Thread thread = new Thread(changeID);
            thread.Start(test);
            //new Thread(changeID).Start(test);
            Thread thread2 = new Thread(changeID);
            thread2.Start(test);
        }
    }
}

结果:
在这里插入图片描述
可以看到,语句不停的在输出nameId等于5,这是为什么呢?
这时候,再让我们好好看看Class1类

class Class1
    {
        private int nameId = 5;

        public void ChangeId()
        {
            
            nameId++;
            if (nameId == 5)
            {
                Console.WriteLine("nameId等于5");
            }
            nameId = 5;
        }
        
    }

我们开启了两个线程同时调用同一个对象的ChangeId方法,当线程一运行到if(name==5),线程二运行到nameId.==5的时候,因为两个线程修改的是同一个对象的同一个nameId,所以就会导致nameId等于5的情况成立,就会满足if条件不停输出 “name等于5”的语句。这个就称为争用条件,那我们要怎么解决这个问题呢?

在这里,我们可以使用lock(锁)解决争用条件的问题

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

namespace 争用条件
{
    class Program
    {
        static void changeID(object o)
        {
            Class1 class1 = o as Class1;

            while (true)
            {
                lock (class1)//向系统申请锁定class1对象,如果class1已经被其他线程锁定,则等待class1对象解锁,再在该线程锁定class1对象,若class1对象未被锁定,则可以直接在该线程将其锁定
                {
                    class1.ChangeId();//在同一个时刻,只有一个线程在执行该方法
                }//当lock结束,则class1对象解锁
          
            }
           
        }

        static void Main(string[] args)
        {
            Class1 test = new Class1();
            Thread thread = new Thread(changeID);
            thread.Start(test);
            //new Thread(changeID).Start(test);
            Thread thread2 = new Thread(changeID);
            thread2.Start(test);
        }
    }
}

结果:
在这里插入图片描述
可以看到现在就输出不了nameId等于5的语句。

但是,如果使用lock不当,会出现死锁情况

死锁例子:


	public void Deadlock1(){
		int i =0;
		while(true){
			lock(s1){
			 	lock(s2){
					s1.ChangeState(i);
					s2.ChangeState(i);
					i++;
					Console.WriteLine("Running i : "+i);
				}
			}
		}
	}
	public void Deadlock2(){
		int i =0;
		while(true){
			lock(s2){
			 	lock(s1){
					s1.ChangeState(i);
					s2.ChangeState(i);
					i++;									
					Console.WriteLine("Running i : "+i);
				}
			}
		}
	}
}

解析:
如果我们线程一现在已经锁定s1等待s2解锁,而线程二现在已经锁定s2等待线程一解锁,这种情况下,线程一永远等不到s2解锁,而且线程二永远等不到线程一解锁,这就出现了死锁情况

那么我们如何解决死锁情况呢

解决:在编程的开始设计阶段,设计锁定顺序

当线程一先锁定s1再锁定s2的时候,线程二也要使用这个锁定顺序,这样就不会出现死锁情况

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值