首页新闻找找看学习计划

一个线程安全问题??Interlocked,Exit方法报错,我的代码写错了??

0
悬赏园豆:20 [已解决问题] 解决于 2016-11-13 18:32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication6
{
    /// <summary>
    /// 同步锁机制
    /// </summary>
    public  class DpLock
    {
        private  long _flag = 0;

        /// <summary>
        /// 尝试获取锁
        /// </summary>
        /// <param name="loop">迭代次数</param>
        /// <returns></returns>
        public  bool TryEnter(int loop=10)
        {
            int _sleep = 5;
            int _times = 10;
            int loopElapse = 0;
            do
            {
                loopElapse++;
                for (int i = 0; i < _times; i++)
                {
                    if (Interlocked.CompareExchange(ref _flag, 1, 0) == 1) //尝试对比交换
                    {
                        return true;  //成功获取锁
                    }
                }
                if (!Thread.Yield())  //尝试请求系统调度其他线程
                {
#if DEBUG
                    Console.WriteLine("sleep"+loopElapse);
#endif
                    //如果系统没有可调度的线程
                    //进入休眠
                    Thread.Sleep(_sleep); 
                }
            } while (loopElapse <= loop);
            return false;
        }

        /// <summary>
        /// 获取锁
        /// <remarks>
        /// </remarks>
        /// </summary>
        public  void Enter()
        {
            int _sleep = 5;
            int _times = 10;
#if DEBUG
            int loopElapse = 0;
#endif
            do
            {
#if DEBUG
                 loopElapse ++;
#endif
                for (int i = 0; i < _times; i++)
                {
                    if (Interlocked.CompareExchange(ref _flag, 1, 0) == 1) //尝试对比交换
                    {
                        return; //成功获取锁
                    }
                }
                if (!Thread.Yield())  //尝试请求系统调度其他线程
                {
#if DEBUG
                    Console.WriteLine("sleep" + loopElapse);
#endif
                    //如果系统没有可调度的线程
                    //进入休眠
                    Thread.Sleep(_sleep);
                }
            } while (true);
        }

        /// <summary>
        /// 释放锁
        /// <remarks>
        /// 这个方法必须要调用,否则其他线程将进入死循环
        /// </remarks>
        /// </summary>
        public  void Exit()
        {
#if DEBUG
            if (Interlocked.Read(ref _flag) != 1)
            {
                //**************   这里报错 _flag值:1  *************** 
                throw new Exception("flag:"+ Interlocked.Read(ref _flag));
            }
#endif
            do
            {
                
            } while (Interlocked.CompareExchange(ref _flag,0,1)==0);
            ;
        }

    }
}
张小军的主页 张小军 | 初学一级 | 园豆:182
提问于:2016-11-10 23:47
< >
分享
最佳答案
0

你外边调用的代码中是不是出现了用TryEnter返回false但同样也尝试Exit了?

代码前半部分没什么问题,但最后这个Exit方法在if条件执行完的时候(前提是上面有包含上面这句话的代码),这个时候读到的是0,但进了throw中的read前有另外一个线程获取到了锁,所以这里你读到的就是1了。

收获园豆:20
Daniel Cai | 专家六级 |园豆:10374 | 2016-11-11 09:32

谢谢,问题找到了,犯了低级错误

张小军 | 园豆:182 (初学一级) | 2016-11-13 18:31
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册