c# - 多线程数组线程安全吗?

标签 c# multithreading

我有这样的代码,一些线程将生成字符串(此处为100)并存储到数组,其他单线程将使用索引器[]读取数据并保存到文件。我在 ThreadSafeString 类中使用 Interlocked 类进行字符串交换,但我不知道它是否足以避免死锁和非线程安全问题。我的另一个想法是使用 ConcurrentDirectory<int, string>确保其安全。

using System;
using System.IO;
using System.Threading;

namespace Test
{
    class ThreadSafeString
    {
        private string _string;

        public string Value
        {
            get => Interlocked.CompareExchange(ref _string, null, null);
            set => Interlocked.Exchange(ref _string, value);
        }
    }

    class Program
    {
        private static readonly ThreadSafeString[] array = new ThreadSafeString[100];

        static void Main(string[] args)
        {
            for (int i = 0; i < 100; i++) array[i] = new ThreadSafeString();

            for (int i = 0; i < 100; i++)
            {
                var thread = new Thread(() =>
                {
                    while (true)
                    {
                        string data = "";
                        //generate data

                        array[i].Value = data;
                        Thread.Sleep(100);
                    }
                });
                thread.Name = i.ToString();
                thread.Start();
            }

            var ht = new Thread(() =>
            {
                while (true)
                {
                    for (int i = 0; i < 100; i++)
                    {
                        string temp = array[i].Value;
                        File.WriteAllText(path, temp);
                    }

                    Thread.Sleep(2000);
                }
            });
            ht.Start();

            Console.ReadKey();
        }
    }
}

最佳答案

我在这里没有看到 ThreadSafeString 的意义。如果您需要将旧数据作为单个操作进行比较、存储和返回,请使用 Interlocked.CompareExchange

Interlocked.CompareExchange(ref _string, null, null);

表示

if (_string == null)
{
    _string = null;
    return null;
} else return _string;

但作为单个操作。如您所见,它可以轻松替换为

return __string;

Interlocked.Exchange相同 - 您不需要对字符串执行此操作:

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/variables#atomicity-of-variable-references

Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types.

仅当您需要以原子操作的形式获取旧值时,才需要对除此之外的类型执行此操作。 在这里简单地使用 string[] 将具有相同的线程安全性。只要不更改数组大小并对引用类型或单字大小的值类型进行操作,您就可以安全地存储和读取数组中的数据。如果你想读取、更改和存储数据,你只需要担心线程安全,但这是另一个问题,甚至连像 ConcurrentDirectory

这样的集合都无法解决。

关于c# - 多线程数组线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58396341/

相关文章:

java - 线程状态监视器。我该如何调试?是什么原因造成的?

java - 使用ReentrantLock和synchronized一样可靠吗?

c# - 无法在 Visual Studio 中为 UWP 应用程序设置 "User Notification Listener"功能

c# - 帮助解决 "Collection was modified; enumeration operation might not execute."

c# - Entity Framework SQL 查询执行

c# - 默认 SynchronizationContext 与默认 TaskScheduler

java - 几秒后自动更改 jSlider

c# - 解析以分号分隔的列表

c# - 服务仅有时会抛出 No 'Access-Control-Allow-Origin' header 错误

.net - 在线程上调用方法,使用异步编程模型的工作任务以及使用BackgroundWorkerThread的工作之间有什么基本区别?