单例模式

单例模式--保证一个类仅有一个实例,并提供一个访问他的全局访问点,该实例被程序所有模块共享。

单例模式结构图

 

特点

  • 通常我们可以让一个全局变量使得一个对象被访问,但不能防止被实例化多个对象。最好方法就是让类自身负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且提供一个访问该实例的方法。
  • 单例模式下,有Singleton类封装其唯一实例,这样它可以严格控制客户端怎样访问以及何时访问。简单来说就是对唯一实例的受控访问。

根据处理方式的不同,单例模式可分为:饿汉模式懒汉模式

饿汉模式:

饿汉模式是通过静态初始化方式,在程序被加载时就实例化创建唯一对象。

class Singleton{
public:
	static Singleton& GetSingleton() // 不能传值,只能传指针或者引用
	{
		cout << "Creat Singleton Object;" << endl;
		return pSing;
	}

private:
	Singleton(){}
	Singleton(const Singleton& pS) = delete;
	static Singleton pSing;
};

Singleton Singleton::pSing;
int main()
{
	Singleton::GetSingleton();
	
	return 0;
}

由于私有化了构造函数、禁用了拷贝构造,所以我们只能通过专门的接口Singleton::GetSingleton()来调用唯一对象。

 

懒汉模式:

懒汉模式是在被调用时才实例化创建唯一对象。

class Singleton{
public:
	static Singleton* GetSingleton() 
	{
		if (pSing == nullptr)
			pSing = new Singleton();
		
		cout << "Creat Singleton Object;" << endl;
		return pSing;
	}

	static void DestorySingleton(){
		delete pSing;
		pSing = nullptr;
		cout << "Destory Success;" << endl;
	}

private:
	Singleton(){}
	Singleton(const Singleton& pS) = delete;
	static Singleton* pSing;
};

Singleton* Singleton::pSing = nullptr;
int main()
{
	Singleton::GetSingleton();
	Singleton::DestorySingleton();

	return 0;
}

 

多线程时的单例:

由于饿汉模式下的单例是静态初始化,在程序运行时唯一对象已经创建好,没有在多个线程访问的安全问题。

但懒汉模式下,可能出现多个线程同时访问Singleton类,调用GetSingleton()方法,可能会创建多个实例。

对于处理线程安全问题上,我们可以通过互斥锁来保证:当一个线程位于代码临界区时,另一个线程不进入临界区,如果其他线程试图进入锁住的代码,它会被一直阻塞,直到该对象被释放

/*
   所以创建互斥锁
   static mutex m;
*/

static Singleton* GetSingleton() 
{
	m.lock();
	if (pSing == nullptr)
		pSing = new Singleton();

	cout << "Creat Singleton Object;" << endl;

	m.unlock();

	return pSing;
}

但是单纯像上面所展示的代码一样,直接加锁,那么每次有线程调用GetSingleton()时,都需要加锁、解锁,而如果已经实例化了对象这样的操作无疑是影响性能的。

改进方式:先进行一次判断,如果已经实例化了对象则,直接返回,不需要等待。

static Singleton* GetSingleton() 
{
	if (pSing == nullptr){
		m.lock();
		if (pSing == nullptr)
			pSing = new Singleton();

		cout << "Creat Singleton Object;" << endl;

		m.unlock();
	}
	return pSing;
}

现在,我们就不用让线程每次都加锁,而只是在实例未被创建时再加锁处理,既提高了效率,也保证了线程安全。这种做法也叫做双重锁定

 

指令重排:

指令重排是一种编译器优化方式,通过调整指令执行顺序,来提高性能。

我们在new创建对象时,通常是:

1. 调用operator new,创建内存空间

2. 调用构造函数,初始化对象 

3. 将对象的地址赋值给指针变量

在第2步 初始化对象是一个内存操作,这可能是一个耗时操作,为了避免CPU在等待这个操作时停顿导致性能下降,编译器会调整指令顺序(开启优化)或者有些架构的CPU会乱序执行指令,也就是将 3 提前执行,这样的话,指针就指向了一个未初始化好的对象。外部得到的单例对象是一个未初始化好的对象,就会引发问题。

考虑到这点,我们可以通过 volatile关键字声明pSing。

static volatile Singleton* pSing;

volatile 作用:

  1.  保证内存可见性。(在多线程环境中,任何线程对共享变量的修改,其他线程都是可感知的。)
  2.  防止指令重排。

 

总结:

饿汉模式与懒汉模式

      饿汉模式:是静态初始化方式,在自己被加载是就将自己实例化;

由于是静态初始化方式,所以程序一加载就需要实例化对象,提前占用系统资源。多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。

但可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。

      懒汉模式:在第一次被引用时,才会将自己实例化。

与饿汉模式不同,是一种延迟启动方式,所以程序启动较快。

但由于调用时才实例化,在多线程下存在线程安全问题,需要双重锁定才能保证安全,实现上比较麻烦。

 

 

 

 

内容概要:本文详细探讨了双馈风力发电机(DFIG)在Simulink环境下的建模方法及其在不同风速条件下的电流与电压波形特征。首先介绍了DFIG的基本原理,即定子直接接入电网,转子通过双向变流器连接电网的特点。接着阐述了Simulink模型的具体搭建步骤,包括风力机模型、传动系统模型、DFIG本体模型和变流器模型的建立。文中强调了变流器控制算法的重要性,特别是在应对风速变化时,通过实时调整转子侧的电压和电流,确保电流和电压波形的良好特性。此外,文章还讨论了模型中的关键技术和挑战,如转子电流环控制策略、低电压穿越性能、直流母线电压脉动等问题,并提供了具体的解决方案和技术细节。最终,通过对故障工况的仿真测试,验证了所建模型的有效性和优越性。 适用人群:从事风力发电研究的技术人员、高校相关专业师生、对电力电子控制系统感兴趣的工程技术人员。 使用场景及目标:适用于希望深入了解DFIG工作原理、掌握Simulink建模技能的研究人员;旨在帮助读者理解DFIG在不同风速条件下的动态响应机制,为优化风力发电系统的控制策略提供理论依据和技术支持。 其他说明:文章不仅提供了详细的理论解释,还附有大量Matlab/Simulink代码片段,便于读者进行实践操作。同时,针对一些常见问题给出了实用的调试技巧,有助于提高仿真的准确性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值