无延迟加载的单例模式 [英] Singleton pattern without lazy loading

查看:87
本文介绍了无延迟加载的单例模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我遇到了需要遵循单例模式的类型的情况,但是该类型不能延迟加载.这是必需的,因为我希望在主线程上创建我的实例-如果使用延迟加载,则将在首先访问该实例的线程上创建该实例.任何建议将不胜感激.

Uros

Hi
I encountered a situation where I need a type of follow the singleton pattern, but the type must not be lazy loaded. This is needed becouse I want my instance to be created on the main thread - if lazy loading is used the instance will be created on the thread that first access the instance. Any advice will be appreciated.

Uros

推荐答案

实际上我不认为这应该是一个问题.如果使用单例模式,则可能正在调用用于初始化对象的共享方法.即使对象是在某个线程上创建的,也不应阻止该对象被其他线程访问(除非它是绑定了线程的某些UI控件,但是在这种情况下,从主线程初始化它不会解决您的问题) ''问题'').据我所知,您的对象是在特定线程上创建的,从特定线程调用,但是存储在与线程无关的同一内存中.
考虑以下代码:
Actually I don''t think this should be a problem. If you are using a singleton pattern you are probably calling a shared method that initializes your object. Even though the object is created on a certain thread this should not prevent it from being accessed from others (unless it''s some UI control that is thread bound, but in that case initializing it from the main thread wouldn''t solve your ''problem''). As far as I know your object is created on a specific thread, called from specific threads, but stored in the same memory that is thread independant.
Consider the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Start a worker thread, initialize the Singleton and set the SomeText Property.
            System.Threading.Tasks.Task.Factory.StartNew(() => SetSingletonText());
            // Simply wait two seconds so we're sure the Singleton instance was set.
            // Don't do this in production code...
            System.Threading.Thread.Sleep(2000);
            // Print the text that was set on a different thread on the main thread.
            PrintSingletonText();
            // Set the text on the main thread.
            SetSingletonText();
            // Print the text that was set on the main thread on the main thread.
            PrintSingletonText();
            // Print the text that was set on the main thread on a different thread.
            // Notice that the console can be accessed from worker threads, unlike, for example, WinForm Controls.
            System.Threading.Tasks.Task.Factory.StartNew(() => PrintSingletonText());
            // Wait for the user the press the 'any' key.
            Console.ReadKey();
        }

        static void SetSingletonText()
        {
            Singleton.GetInstance().SomeText =
                  String.Format("Hello from thread {0}!", System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
        }

        static void PrintSingletonText()
        {
            Console.WriteLine(String.Format("Written on Thread {0}: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, Singleton.GetInstance().SomeText));
        }
    }

    class Singleton
    {
        private static Singleton _singleton;

        public string SomeText { get; set; }

        public static Singleton GetInstance()
        {
            if (_singleton == null)
            {
                _singleton = new Singleton();
            }
            return _singleton;
        }

    }
}

运行它并读取结果.
如您所见,我可以从任何线程获取并设置SomeText.但是,您必须确保您的类是线程安全的.
例如,如果您有一个值为1的整数变量,然后从一个线程中将其乘以2,然后从另一个线程中将其乘以3,则线程访问该变量的顺序将影响您的结果!如果您首先将1乘以2(即2),然后再加上3,那么您将得到5.如果您先加上3,然后再乘以2,您将得到8.这也称为比赛条件 [ ^ ].
如果需要从另一个线程同步到主线程,则还有其他方法可用,具体取决于启动线程的方式.
在多线程环境中使用类或方法,但是只有在特定线程上创建了类或方法后,才能使它起作用,这听起来像是一个坏主意.您的同事可能不知道您的意图,甚至会在工作线程上调用初始化您的对象的方法!
欲了解更多信息,请参见:
线程教程(C#) [线程同步(C#和Visual Basic) [

Run it and read the results.
As you can see I can get and set SomeText from any thread. You DO have to make sure your class is thread safe though.
If, for example, you have an integer variable with value 1 and multiply it by 2 from one thread and then add 3 from another thread the order in which the threads access the variable will affect your outcome! If you FIRST multiply 1 by 2 (which is 2) and then add 3 you''ll have 5. If you first add 3 and then multiply by 2 you''ll have 8. This is also known as a race condition[^].
If you need to synchronize to your main thread from another thread there are also other methods available, depending on how you are starting your thread.
Using a class or method in a multithreaded environment, but only making it work if it was created on some specific thread sounds like a bad idea. Your co-workers may not know your intentions or will even call the method that initializes your object on a worker thread!
For further reading see:
Threading Tutorial (C#)[^]
Thread Synchronization (C# and Visual Basic)[^]

Of course you could still simply call your method on the main thread and hope it will stay that way. It''s your call :)


编写一个静态方法,该方法初始化该实例,并在首次访问该类之前从主线程调用该实例.
Write a static method that initializes the instance and call it from the main thread before the class is first accessed.


这篇关于无延迟加载的单例模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆