Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 被调用实例方法中的锁定问题_C#_.net_Multithreading_Thread Safety_Locking - Fatal编程技术网

C# 被调用实例方法中的锁定问题

C# 被调用实例方法中的锁定问题,c#,.net,multithreading,thread-safety,locking,C#,.net,Multithreading,Thread Safety,Locking,我一直在学习albahari线程课程,但当我自己去做实验时,事情并没有按计划进行。我不知道为什么下面的锁“_lock”不起作用。不知何故,每个SafeLock方法中的锁都不会阻止其他线程也使用其方法。我在这里已经有一段时间了,所以我们非常感谢您的帮助 //Here I just call a method 10x //The method (SL1) then creates a SafeLocks object and runs 3 methods private void SL1_Btn_C

我一直在学习albahari线程课程,但当我自己去做实验时,事情并没有按计划进行。我不知道为什么下面的锁“_lock”不起作用。不知何故,每个SafeLock方法中的锁都不会阻止其他线程也使用其方法。我在这里已经有一段时间了,所以我们非常感谢您的帮助

//Here I just call a method 10x
//The method (SL1) then creates a SafeLocks object and runs 3 methods
private void SL1_Btn_Click(object sender, EventArgs e)
{
    SL1(); SL1(); SL1(); SL1(); SL1();
    SL1(); SL1(); SL1(); SL1(); SL1();
}
private void SL1()
{
    console.WriteLine("Thread Enter");
    SafeLocks sl = new SafeLocks();
    ThreadPool.QueueUserWorkItem(o => sl.ShowVars());
    ThreadPool.QueueUserWorkItem(o => sl.SetZero());
    ThreadPool.QueueUserWorkItem(o => sl.ShowVars());
    console.WriteLine("Thread Exit");
}

//Now for the Thread-"Safe" class
    class SafeLocks
{
    //private static int staticVar = 1; 
    private static int staticVar = 1; 
    public int instanceVar = 1;
    private static readonly object _Lock = new object();

    public SafeLocks() //sets both to 100,000
    {
        lock (_Lock)
        {
            while (staticVar < 99999)
            { staticVar++; }
            while (instanceVar < 99999)
            { instanceVar++; }
            staticVar++;
            instanceVar++;
            if (instanceVar != 100000)
            { Console.WriteLine("I1=" + instanceVar.ToString()); }
            if (staticVar != 100000)
            { Console.WriteLine(("S1=" + staticVar.ToString())); }
        }
    }
    public void ShowVars()
    {
        lock (_Lock)
        {
            if (instanceVar != 100000 && instanceVar != 0)
            { Console.WriteLine("I2=" + instanceVar.ToString()); }
            if (staticVar != 100000 && staticVar != 0)
            { Console.WriteLine("S2=" + staticVar.ToString()); }
        }
    }
    public void SetZero()
    {
        lock (_Lock)
        {
            while (staticVar > 0)
            {
                staticVar--;
            }
            while (instanceVar > 0)
            {
                instanceVar--;
            }
            if (instanceVar != 0)
            { Console.WriteLine("I3=" + instanceVar.ToString()); }
            if (staticVar != 0)
            { Console.WriteLine("S3=" + staticVar.ToString()); }
        }
    }
}
//这里我只调用一个方法10x
//然后,该方法(SL1)创建一个SafeLocks对象并运行3个方法
私有无效SL1\u Btn\u单击(对象发送方,事件参数e)
{
SL1();SL1();SL1();SL1();SL1();SL1();
SL1();SL1();SL1();SL1();SL1();SL1();
}
私有无效SL1()
{
console.WriteLine(“线程输入”);
SafeLocks sl=新的SafeLocks();
ThreadPool.QueueUserWorkItem(o=>sl.ShowVars());
ThreadPool.QueueUserWorkItem(o=>sl.SetZero());
ThreadPool.QueueUserWorkItem(o=>sl.ShowVars());
控制台写入线(“线程退出”);
}
//现在是线程“安全”类
类安全锁
{
//私有静态int staticVar=1;
私有静态int staticVar=1;
公共int instanceVar=1;
私有静态只读对象_Lock=new object();
public SafeLocks()//将两者都设置为100000
{
锁
{
而(staticVar<99999)
{staticVar++;}
而(instanceVar<99999)
{instanceVar++;}
staticVar++;
instanceVar++;
如果(instanceVar!=100000)
{Console.WriteLine(“I1=“+instanceVar.ToString());}
如果(静态变量!=100000)
{Console.WriteLine((((('S1=“+staticVar.ToString())));}
}
}
公共void ShowVars()
{
锁
{
如果(instanceVar!=100000&&instanceVar!=0)
{Console.WriteLine(“I2=“+instanceVar.ToString());}
如果(staticVar!=100000&&staticVar!=0)
{Console.WriteLine(“S2=“+staticVar.ToString());}
}
}
公共void SetZero()
{
锁
{
而(staticVar>0)
{
静态变量--;
}
while(instanceVar>0)
{
实例变量--;
}
如果(instanceVar!=0)
{Console.WriteLine(“I3=“+instanceVar.ToString());}
如果(staticVar!=0)
{Console.WriteLine(“S3=“+staticVar.ToString());}
}
}
}

}

问题源于构造函数的组合,以及正在构造或调用
SetZero的多个实例之间没有线程安全这一事实。也就是说,在调用
SetZero
之前,可以创建两个实例。(编辑:您现在拥有的锁功能正常,没有方法可以同时执行,但它们不能保证从外部调用这些方法的顺序。您设置的线程在调用
SetZero
之前,最终多次调用对象构造函数(制作精美。)

首先在构造函数中(注意,我消除了
instanceVar
用法,因为它运行正常):

如果将构造函数代码更改为:

lock (_Lock)
{
    while (staticVar <= 99999) //note the <= comparison change
    { staticVar++; }
    while (instanceVar <= 99999) //note the <= comparison change
    { instanceVar++; }
    if (instanceVar != 100000)
    { Console.WriteLine("I1=" + instanceVar.ToString()); }
    if (staticVar != 100000)
    { Console.WriteLine(("S1=" + staticVar.ToString())); }
}
lock(\u lock)
{

虽然(staticVar旁注:我认为没有一种命名约定允许调用任何参数
\u Lock
Aha!多亏了您的回答,我现在对锁定有了更好的理解。随着工作线程的创建,它们会运行到操作系统堆栈中,因此即使最初的调用线程以10倍的顺序执行,工作线程的顺序也可以更改。)有些随意,他们中的许多人可能会以一种不希望的方式出现在对方面前。你对这一点的解释非常有帮助!
SafeLocks sl = new SafeLocks();
SafeLocks s2 = new SafeLocks(); //outputs "S1=100001"
SafeLocks s3 = new SafeLocks(); //outputs "S1=100002"
SafeLocks s4 = new SafeLocks(); //outputs "S1=100003"
SafeLocks s5 = new SafeLocks(); //outputs "S1=100004"
lock (_Lock)
{
    while (staticVar <= 99999) //note the <= comparison change
    { staticVar++; }
    while (instanceVar <= 99999) //note the <= comparison change
    { instanceVar++; }
    if (instanceVar != 100000)
    { Console.WriteLine("I1=" + instanceVar.ToString()); }
    if (staticVar != 100000)
    { Console.WriteLine(("S1=" + staticVar.ToString())); }
}