线程内的线程

时间:2016-10-28 02:55:47

标签: c# multithreading windows-services

thread将使用class来处理特定交易。但要求是,当两个线程同时访问此class时,此class需要是一个避免减速的线程。我如何制作thread

3 个答案:

答案 0 :(得分:0)

可以使用锁或Monitor.Enter逻辑同步多线程应用程序之间的共享资源。以下是几个基本多线程理解的参考链接

答案 1 :(得分:0)

当多个线程同时访问某个对象时,没有固有的减速,但如果数据读写混合,则可能会遇到竞争条件问题。一个典型的解决方案是使用lock statementsynchronize access to the object。请记住,多线程编程很难做到正确。

答案 2 :(得分:0)

我举例说明了如何安全地从多个线程访问资源。

线程不安全版本

class Program
{
    private static decimal _balance = 100;

    static void Main(string[] args)
    {
        for (var i = 0; i < 10; i++)
        {
            ThreadPool.QueueUserWorkItem(Withdraw, 23m);
        }

        Console.ReadLine();
    }

    private static void Withdraw(object state)
    {
        var value = (decimal)state;
        var prevBalance = _balance;

        if (_balance >= value)
        {
             Thread.Sleep(50); // simulate longer operation to emphasize data corruption
            _balance = _balance - value;
            Console.WriteLine("Balance {0}. Withdraw {1}. Balance after withdraw {2}", prevBalance, value, _balance);
        }

        Console.WriteLine("Balance {0}. Withdraw failed", prevBalance);        
    }
}    

此代码将导致意外(和不可预测)的结果,因为变量_balance同时从多个线程访问和写入。 _balance可能是负面的,尽管我们在撤销前检查余额。

结果

Result1

线程安全版

要使撤销方法在线程安全之上,你需要在lock语句中包装方法体。

class Program
{
    private static decimal _balance = 100;
    private static readonly object _balanceLocker = new object();

    static void Main(string[] args)
    {
        for (var i = 0; i < 10; i++)
        {
            ThreadPool.QueueUserWorkItem(Withdraw, 23m);
        }

        Console.ReadLine();
    }

    private static void Withdraw(object state)
    {
        lock (_balanceLocker)
        {
            var value = (decimal)state;
            var prevBalance = _balance;

            if (_balance >= value)
            {
                Thread.Sleep(50); // simulate longer operation to emphasize data corruption
                _balance = _balance - value;
                Console.WriteLine("Balance {0}. Withdraw {1}. Balance after withdraw {2}", prevBalance, value, _balance);
                return;
            }

            Console.WriteLine("Balance {0}. Withdraw {1}. Withdraw failed", prevBalance, value);
        }
    }
}    

使用上面的代码,从多个线程访问eventhough _withdraw,它永远不会为零。

结果

enter image description here