Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.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# 在.net中锁定将如何运行? 抽象类Foo { 私有列表容器; 私有布尔更新; Foo Foo() { 容器=新列表(); 更新=假; } 公共抽象条CreateBar(); public void BeginUpdate() { 如果(!更新) { 线程更新_Thread=新线程(新线程开始(更新)); 更新_thread.Start(); } } 私有void更新() { 更新=真; while(更新) { 锁(容器) { 如果(…) container.Add(this.CreateBar()); 其他的 容器。移除(…); } 睡眠(1337); } } public void EndUpdate() { 更新=假; } 公共列表对象 { 得到 { 锁(容器) { 退回这个集装箱; } } } }_C#_.net_Multithreading_Locking - Fatal编程技术网

C# 在.net中锁定将如何运行? 抽象类Foo { 私有列表容器; 私有布尔更新; Foo Foo() { 容器=新列表(); 更新=假; } 公共抽象条CreateBar(); public void BeginUpdate() { 如果(!更新) { 线程更新_Thread=新线程(新线程开始(更新)); 更新_thread.Start(); } } 私有void更新() { 更新=真; while(更新) { 锁(容器) { 如果(…) container.Add(this.CreateBar()); 其他的 容器。移除(…); } 睡眠(1337); } } public void EndUpdate() { 更新=假; } 公共列表对象 { 得到 { 锁(容器) { 退回这个集装箱; } } } }

C# 在.net中锁定将如何运行? 抽象类Foo { 私有列表容器; 私有布尔更新; Foo Foo() { 容器=新列表(); 更新=假; } 公共抽象条CreateBar(); public void BeginUpdate() { 如果(!更新) { 线程更新_Thread=新线程(新线程开始(更新)); 更新_thread.Start(); } } 私有void更新() { 更新=真; while(更新) { 锁(容器) { 如果(…) container.Add(this.CreateBar()); 其他的 容器。移除(…); } 睡眠(1337); } } public void EndUpdate() { 更新=假; } 公共列表对象 { 得到 { 锁(容器) { 退回这个集装箱; } } } },c#,.net,multithreading,locking,C#,.net,Multithreading,Locking,当Foo之外的东西调用Foo的对象访问器时 abstract class Foo { private List<Object> container; private bool update; Foo Foo() { container = new List<object>(); update = false; } public abstract Bar CreateBar();

当Foo之外的东西调用Foo的对象访问器时

abstract class Foo
{
    private List<Object> container;
    private bool update;

    Foo Foo()
    {
        container = new List<object>();
        update = false;
    }

    public abstract Bar CreateBar();

    public void BeginUpdate()
    {
        if (!update)
        {
            Thread update_thread = new Thread(new ThreadStart(Update));
            update_thread.Start();
        }
    }

    private void Update()
    {
        update = true;
        while (update)
        {
            lock (container)
            {
                if (...)
                    container.Add(this.CreateBar());
                else
                    container.Remove(...);
            }

            Thread.Sleep(1337);
        }
    }

    public void EndUpdate()
    {
        update = false;
    }

    public List<Object> Objects
    {
        get
        {
            lock (container)
            {
                return this.container;
            }
        }
    }
}
List objects=foo\u instance.objects;
foreach(对象中的对象o)
{
睡眠(31173);
}

锁定将如何发生?运行Update()的线程是否必须等待上述foreach处理完对象列表?我希望这两个功能同时工作,这是创建对象深度副本的唯一解决方案吗?

您可以认为锁定范围类似于函数范围。在访问器方法内部执行锁定只会在大括号之间锁定,一旦返回值,锁将被释放。您需要在类之外(在调用方中)执行锁定以获得所需的效果


因此,循环和线程都能够同时访问对象。这是不好的,因为如果线程在循环过程中更改对象,循环将抛出异常,因为集合已被修改。

您的代码没有执行您认为它会执行的操作。这种方法

List<Objects> objects = foo_instance.Objects;
foreach (Object o in objects)
{
    Thread.Sleep(31173);
}
公共列表对象
{
得到
{
锁(容器)
{
退回这个集装箱;
}
}
}
在返回值后不保持锁。所以你的循环没有被锁定


无法从clas返回容器实例此代码存在以下问题:

  • 你没有启动线程
  • 您可以有一个争用条件(可能不适用于您的程序),其中多个线程调用BeginUpdate,两个线程都看到更新为false,并且都启动一个线程,现在您有两个线程正在运行,可能会相互干扰,因为您有一个共享数据的字段成员
  • 锁定该属性有什么意义?你不需要它。请注意,由于内部更新,从属性返回的容器有时会处于不断变化的状态。这意味着调用属性的外部代码必须在访问容器内容之前锁定容器本身。不过,返回容器引用不需要锁
  • 竞争条件如果调用EndUpdate,然后紧接着调用BeginUpdate,则旧线程可能还没有退出的机会

  • 我想说的是,在您开始担心锁定什么以及何时锁定之前,您应该修复代码,这样它就不会有很多其他与线程相关的问题。

    krosenvald是正确的,只要属性返回指向容器对象的指针,对象访问器上的锁就会被释放

    在你的代码中

    public List<Object> Objects
    {
        get
        {
            lock (container)
            {
                return this.container;
            }
        }
    }
    
    List objects=foo\u instance.objects;
    foreach(对象中的对象o)
    {    
    睡眠(31173);
    }
    

    锁只适用于第一行。。。正在填充引用变量“objects”的位置。。。实际上没有必要为该行锁定任何内容,因为没有通过获取指针修改内存

    如果在foreach内部使用和访问对象“o”,是否会有可能的访问冲突?那么,“访问冲突”是什么意思?当然不会有任何锁争用,因为在foreach开始时锁的目标将释放locj…谢谢,很好的洞察力。因为我不能投票,我不得不口头批评你
    List<Objects> objects = foo_instance.Objects;
    foreach (Object o in objects)
    {    
        Thread.Sleep(31173);
    }