Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.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_Garbage Collection_Synchronization - Fatal编程技术网

C# 从多个线程分配和获取对象引用是否需要同步代码?

C# 从多个线程分配和获取对象引用是否需要同步代码?,c#,.net,multithreading,garbage-collection,synchronization,C#,.net,Multithreading,Garbage Collection,Synchronization,免责声明:此代码永远连续运行两个线程。自担风险 using System; using System.Threading.Tasks; namespace ConsoleApp126 { internal class AnyClass { private int _state;// = 0 public AnyClass() { _state = 1; } ~AnyCla

免责声明:此代码永远连续运行两个线程。自担风险

using System;
using System.Threading.Tasks;

namespace ConsoleApp126
{
    internal class AnyClass
    {
        private int _state;// = 0

        public AnyClass()
        {
            _state = 1;
        }

        ~AnyClass()
        {
            _state = 2;
        }

        public void TestState()
        {
            if (_state != 1)
                throw new Exception("Already finalized");
        }
    }

    internal class Tester
    {
        private AnyClass _any = new AnyClass();
        private object _sync = new object();

        public void Initialize()
        {

            //lock(_sync)
                _any = new AnyClass();

            GC.Collect();
            GC.WaitForFullGCComplete();
            GC.WaitForPendingFinalizers();
        }

        public void Test()
        {
            AnyClass any;

            //lock (_sync)
                any = _any;
                //  mov         eax,dword ptr [ebp-3Ch] 
                //  mov         eax, dword ptr[eax + 4] // What if a context switch happens after this instruction?
                //  mov         dword ptr[ebp - 40h], eax

            any.TestState();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var tester = new Tester();

            Task.Run(() =>
            {
                try
                {
                    while (true)
                        tester.Initialize();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            });

            Task.Run(() =>
            {
                try
                {
                    while (true)
                        tester.Test();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            });

            Console.ReadLine();
        }
    }
}
在没有同步代码的情况下,从多个线程分配和获取对象引用是否安全

在这两种情况下都不应该取消对lock(_sync)语句的注释,以确保垃圾收集是安全的吗

如果没有,如果在“mov eax,dword ptr[eax+4]”之后有上下文切换,并且GC收集eax中引用的对象,会发生什么情况。那么,当“mov dword ptr[ebp-40h],eax”最终将对象引用分配给变量“any”时,引用不可能无效吗?我在没有锁的情况下运行了12个小时的代码,没有发现任何不良行为。有人能解释一下这是怎么回事吗


我在Windows101909上使用了VS2017。以.NET 4.71和x86为目标。

您想证明什么?引用的原子性?GC知道如何检查寄存器-它们被视为GC根。基本上:这不是问题。不,它不需要同步。是的,我试图确认引用的绝对原子性。我已经知道,由于线程访问冲突,您不会读取或写入损坏的引用,因为所有内存“结构”的默认对齐方式是内存总线宽度的一个因素,可能至少为8个字节。
lock
语句不仅同步线程之间对共享资源的访问,它还添加了内存屏障,以便从下一个线程可以看到由一个线程引起的更改。因此,通过移除锁,您可能不会遇到原子性问题,但您可能会遇到可见性问题。锁定是安全的选择。无锁多线程是脆弱和危险的。在调用
TestState
之前,是否真的收集了
\u any
,这是一个巨大的疑问。标记阶段开始时,停止并分析所有线程。目前,
\u任何
都将出现在调用
TestState
的线程中,因此将避免收集和终结,因为它们不会被标记为“未使用”。您在这里试图证明什么?引用的原子性?GC知道如何检查寄存器-它们被视为GC根。基本上:这不是问题。不,它不需要同步。是的,我试图确认引用的绝对原子性。我已经知道,由于线程访问冲突,您不会读取或写入损坏的引用,因为所有内存“结构”的默认对齐方式是内存总线宽度的一个因素,可能至少为8个字节。
lock
语句不仅同步线程之间对共享资源的访问,它还添加了内存屏障,以便从下一个线程可以看到由一个线程引起的更改。因此,通过移除锁,您可能不会遇到原子性问题,但您可能会遇到可见性问题。锁定是安全的选择。无锁多线程是脆弱和危险的。在调用
TestState
之前,是否真的收集了
\u any
,这是一个巨大的疑问。标记阶段开始时,停止并分析所有线程。目前,
\u任何
都将出现在调用
TestState
的线程中,因此将避免收集和完成,因为不会标记为“未使用”。