- 浏览: 332582 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (140)
- oracle (2)
- j2se (18)
- 应用服务器 (2)
- 操作系统 (21)
- j2ee (3)
- web (9)
- Junit (0)
- 项目 (0)
- IDE (0)
- 五花八门 (1)
- excel导入导出 (0)
- DWR (0)
- display标签总结 (0)
- JS (7)
- FCKeditor (0)
- Spring (3)
- webservice (1)
- JVM (14)
- 传输协议 (6)
- maven (3)
- 服务器 (2)
- 数据结构 (11)
- HTTPClient (2)
- JQUERY (9)
- 设计模式 (4)
- 数据库 (6)
- 看书笔记 (0)
- 工具 (4)
- MINA (3)
- mysql (5)
- jetty (1)
- JAVA网络编程 (7)
- Hessian (1)
- ibatis (1)
- socket (4)
- Native (1)
- http (2)
- nosql (2)
- linux (1)
- hadoop (1)
最新评论
-
applezjv:
可以...
maven常见问题 -
andyboy_bin:
p
Jetty -
ye_wx:
...
TableSpace -
ye_wx:
TableSpace -
极限_裁决:
引用第二:不要把“好像”;“有人会……”;“大概”;“晚些时候 ...
可以让你少奋斗10年的工作经验
spring单利bean和线程安全
Spring的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求 都创建一个单独的Sevlet线程来处理请求,引入Spring框架之后,每个Action都是单例的,那么对于Spring托管的单例Service Bean,如何保证其安全呢?本文介绍了以上的安全问题。
Spring的原型Bean与单例Bean的设置
spring单例Bean
在spring中的Bean缺省的情况下是单例模式的,在spring容器中分配Bean的时候(无论通过getBean()还是通过依赖注入(IOC)),它总是返回同一个Bean的实例,如果你想每次向上下文请求一个bean的时候总是得到一个不同的实例,或者想每次想从spring容器中得到一个bean的不同实例,需要将bean定义为原型模式,定义为原型模式意味着你是定义一个bean的类,而不是一个单一的bean的实例,bean的实例都是按照这个类而创建的。
spring原型Bean
在spring中<bean>的singleton属性告诉上下文这个bean是原型bean或者是单例bean。bean的缺省值为
true,如果设为false的话,就把这个bean定义成了原型bean。例如:<beanid=”test”
class=”demo.Demo” singleton=”false” />
在spring2.x中<bean id=”test”scope=”prototype”/>将这样配置,但是如果想使用spring的原型bean必须通过 getBean(”test”)这样的方 式,而不能通过使用IOC方式,因为:getBean将每次都有spring来装配转发,而IOC将只是一次注入的目标bean中,以后不再重新注入。这 样通过getBean方式将得到一个原型bean。如果bean使用的是有限资源,如数据库和网络链接的话不需要使用原型bean,正常不要把 singleton=”false”或者scope=”prototype”除非必要。
Spring 单例Bean和Java 单例模式的区别
Spring的的单例是基于BeanFactory也就是spring容器,单例Bean在此Spring容器内是单个的,Java的单例是基于JVM,每个JVM内一个单例。
线程安全
Thread safety is a computer programming concept applicable in thecontext of multi-threaded programs. A piece of codeis thread-safe if it can be safely invoked by multiple threads at thesame time [1].
Thread safety is a key challenge in multi-threadedprogramming. It was not a concern for most application programmers of littlehome applications, but since the 1990s, as Windows became multithreaded, andwith the expansion of BSD and Linux operating systems, it has become acommonplace issue. In a multi-threaded program, several threads executesimultaneously in a shared address space. Every thread has access to virtuallyall the memory of every other thread. Thus the flow ofcontrol and the sequence of accesses to data often have little relation to whatwould be reasonably expected by looking at the text of the program, violatingthe principle of least astonishment.Thread safety is a property that allows code to run in multi-threadedenvironments by re-establishing some of the correspondences between the actualflow of control and the text of the program, by means of Process synchronization.
Identification
It is not easy to determine if a piece of code isthread-safe or not. However, there are several indicators that suggest the needfor careful examination to see if it is unsafe:
- accessing global variables or the heap
- allocating/reallocating/freeing resources that have global scope (files, sub-processes, pipes, etc.)
- indirect accesses through handles or pointers
- any visible side-effect (e.g., access to volatile variables in the C programming language)
Implementation
There are a few ways to achieve thread safety:
Writing code insuch a way that it can be partially executed by one task, reentered by another task, and thenresumed from the original task. This requires the saving of state information in variables local toeach task, usually on its stack, instead of in staticor global variables. There are still some rare caseswhere a static variable can be used in a reentrant function, if the access isdone through atomic operations.
Mutualexclusion or Process synchronization
Access to shareddata is serialized using mechanisms that ensure only one thread reads orwrites the shared data at any time. Great care is required if a piece of codeaccesses multiple shared pieces of data—problems include raceconditions, deadlocks,livelocksand starvation.
Variables arelocalized so that each thread has its own private copy. These variables retaintheir values across subroutine and other code boundaries, and are thread-safesince they are local to each thread, even though the code which accesses themmight be reentrant.
Shared data areaccessed by using atomic operations which cannot be interrupted by otherthreads. This usually requires using special machinelanguage instructions, which might be available in a runtimelibrary. Since the operations are atomic, the shared data are always keptin a valid state, no matter what other threads access it. Atomicoperations form the basis of many thread locking mechanisms.
Examples
In the following piece of C code, the function is thread-safe, butnot reentrant
int function()
{
mutex_lock();
...
function body
...
mutex_unlock();
}
In the above, function
can be called bydifferent threads
without any problem. But if the function is used in areentrant
interrupt handler and a second interrupt arises inside the function,the
second routine will hang forever. As interrupt servicing
can disable otherinterrupts, the whole system could suffer.
Concurrent programing
Note that a piece of code can be thread safe, and yet notbeing able to run at the same time that some other piece of code is running. Atrivial example of that is when that other piece of code restarts the computer.The following piece of C code, presents a less obvious situationwhere a thread is using a file that another thread or process might delete.
int function()
{
char *filename = "/etc/config";
FILE *config;
if (file_exist(filename)){
config = fopen(filename);
}
}
In the above, the function is thread-safe, as it can becalled from any number of threads and will not fail. But all the calls shouldbe in a controlled environment. If executed in a multi-process environment, orif the file is stored on a network-shared drive, there is no warranty that itwon't be deleted.
Difficulties
One approach to making data thread-safe that combinesseveral of the above elements is to make changes atomicallyto update the shared data. Thus, most of the code is concurrent, and little time is spentserialized.
可重入函数与不可重入函数
主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断 它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它 如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。
也可以这样理解,重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖 于任何环境(包括static),这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以 不会互相干扰。如果确实需要访问全局变量(包括static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量 付出一些性能代价。
编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。
说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。
示例:假设Exam是int型全局变量,函数Squre_Exam返回Exam平方值。那么如下函数不具有可重入性。
unsigned int example( int para )
{
unsigned int temp;
Exam = para; // (**)
temp = Square_Exam( );
return temp;
}
此函数若被多个进程调用的话,其结果可能是未知的,因为当(**)语句刚执行完后,另外一个使用本函数的进程可能正好被激活,那么当新激活的进程执行到此
函数时,将使Exam赋与另一个不同的para值,所以当控制重新回到“temp = Square_Exam(
)”后,计算出的temp很可能不是预想中的结果。此函数应如下改进。
unsigned int example( int para ) {
unsigned int temp;
[申请信号量操作] //(1)
Exam = para;
temp = Square_Exam( );
[释放信号量操作]
return temp;
}
(1)若申请不到“信号量”,说明另外的进程正处于给Exam赋值并计算其平方过程中(即正在使用此信号),本进程必须等待其释放信号后,才可继续执行。若申请到信号,则可继续执行,但其它进程必须等待本进程释放信号量后,才能再使用本信号。
保证函数的可重入性的方法:
在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量),对于要使用的全局变量要加以保护(如采取关中断、信号量等方法),这样构成的函数就一定是一个可重入的函数。
VxWorks中采取的可重入的技术有:
* 动态堆栈变量(各子函数有自己独立的堆栈空间)
* 受保护的全局变量和静态变量
* 任务变量
--------------------------------------------------
在
实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任
务调用这个函数的数据,从而导致不可预料的后果。那么什么是可重入函数呢?所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是
否会出错。不可重入函数在实时系统设计中被视为不安全函数。满足下列条件的函数多数是不可重入的:
1) 函数体内使用了静态的数据结构;
2) 函数体内调用了malloc()或者free()函数;
3) 函数体内调用了标准I/O函数。
下面举例加以说明。
A. 可重入函数
void strcpy(char *lpszDest, char *lpszSrc)
{
while(*lpszDest++=*lpszSrc++);
*dest=0;
}
B. 不可重入函数1
charcTemp;//全局变量
void SwapChar1(char *lpcX, char *lpcY)
{
cTemp=*lpcX;
*lpcX=*lpcY;
lpcY=cTemp;//访问了全局变量
}
C. 不可重入函数2
void SwapChar2(char *lpcX,char *lpcY)
{
static char cTemp;//静态局部变量
cTemp=*lpcX;
*lpcX=*lpcY;
lpcY=cTemp;//使用了静态局部变量
}
问题1,如何编写可重入的函数?
答:在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。
问题2,如何将一个不可重入的函数改写成可重入的函数?
答:把一个不可重入函数变成可重入的唯一方法是用可重入规则来重写它。其实很简单,只要遵守了几条很容易理解的规则,那么写出来的函数就是可重入的。
1) 不要使用全局变量。因为别的代码很可能覆盖这些变量值。
2) 在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”。
3) 不能调用其它任何不可重入的函数。
4) 谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。
堆栈操作涉及内存分配,稍不留神就会造成益出导致覆盖其他任务的数据,所以,请谨慎使用堆栈!最好别用!很多黑客程序就利用了这一点以便系统执行非法代码从而轻松获得系统控制权。还有一些规则,总之,时刻记住一句话:保证中断是安全的!
实例问题:曾经设计过如下一个函数,在代码检视的时候被提醒有bug,因为这个函数是不可重入的,为什么?
unsigned int sum_int( unsigned int base )
{
unsigned int index;
static unsigned int sum = 0; // 注意,是static类型
for (index = 1; index <= base;index++)
sum += index;
return sum;
}
分析:所谓的函数是可重入的(也可以说是可预测的),即只要输入数据相同就应产生相同的输出。这个函数之所以是不可预测的,就是因为函数中使用了
static变量,因为static变量的特征,这样的函数被称为:带“内部存储器”功能的的函数。因此如果需要一个可重入的函数,一定要避免函数中使用
static变量,这种函数中的static变量,使用原则是,能不用尽量不用。
将上面的函数修改为可重入的函数,只要将声明sum变量中的static关键字去掉,变量sum即变为一个auto类型的变量,函数即变为一个可重入的函数。
当然,有些时候,在函数中是必须要使用static变量的,比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。
Spring单例的线程安全
基本上,Spring的thread-safe是其API自身的thread-safe。比如一个常见的场景(from appfuse): |
另一篇参考:http://www.coderanch.com/t/60676/oa/Thread-safe-spring-application
相关推荐
在`DoubleCheckSingletion`类中,`getInstance()`方法先进行了一次空值检查,只有当实例为`null`时才会进入同步代码块,这样既保证了线程安全又提高了性能。 #### 五、总结 单例设计模式是一种重要的设计模式,...
3. **登记式单例**(Registry Singleton,或双检锁/双重校验锁模式,DCL,Double-Checked Locking):结合了懒汉式和饿汉式的优点,它在多线程环境下既保证了性能又实现了线程安全。这种方式使用volatile关键字来...
单利、复利和年金的计算 单利、复利和年金是金融计算中的三大基础概念,分别指在不同计算模式下对资金的价值计算。其中,单利是指在计算利息时,每一期的利息仅计算本金的利息,而不计算利息的利息;复利则是指在...
我们使用`dispatch_once`保证`sharedInstance`只被初始化一次,确保线程安全。这样,无论何时调用`+ (instancetype)sharedInstance`,都会返回同一个`MySingleton`对象。 在`AppDelegate`中,我们可以像下面这样...
另外,考虑到C++11及更高版本提供了更高级的特性,如`std::call_once`和`std::once_flag`,可以用来更优雅地处理线程安全的单例初始化。 总之,单例模式是一种控制类实例化的策略,用于确保类只有一个实例,并提供...
3. **双检锁/双重校验锁定(DCL,Double-Check Locking)**:结合了懒汉式和饿汉式的优点,既延迟初始化,又保证了线程安全。 ```java public class Singleton { private volatile static Singleton INSTANCE; ...
在金融和经济领域,利息是资金成本或投资收益的关键因素,单利和复利是两种基本的计算利息的方法。此“单利与复利的比较.rar”文件包含了一个Excel工作簿,通过具体实例展示了这两种计算方式的区别。接下来,我们将...
这个“Excel模板存款单利终值计算与分析.zip”文件包含了一个名为“存款单利终值计算与分析.xlsx”的Excel表格,旨在帮助用户方便地进行存款单的利息计算和分析。下面我们将详细探讨相关的知识点。 1. **存款单**:...
详细讲述了工厂,抽象工厂,单利模式!以及各种设计模式的简述,让你轻松掌握!
编写程序,计算理财收益中复利与单利的差额.txt
总之,"ios-单利实现控制器之间的跳转.zip"项目探讨了如何使用单例模式来统一管理TabBarController和控制器之间的导航逻辑。通过这种方式,开发者可以更高效地控制界面的流转,同时保持代码的清晰和可维护性。在实际...
本压缩包文件"Excel模板单利现值的计算与资金变化.zip"包含了"单利现值的计算与资金变化.xlsx"这个Excel模板,旨在帮助用户更直观、便捷地理解和计算单利现值,同时跟踪资金的变化情况。 首先,我们要理解单利现值...
在Java编程语言中,我们...总结来说,要创建一个Java程序来计算单利,你需要定义本金、年利率和时间,然后应用上述公式。这两个示例演示了如何在实际代码中实现这个计算,它们可以作为模板,根据实际需求调整输入参数。
4. 结合`__new__`和线程锁,保证多线程环境下的线程安全。 每种方法都有其适用场景,需要根据项目需求和环境选择合适的实现方式。在实际开发中,理解并灵活运用这些单例模式的实现方式,可以有效地管理和控制类的...
这些概念都是为了让程序各组件之间的通信更加高效和灵活。以下将详细介绍这些知识点: 1. **界面传值**:在iOS应用中,不同视图控制器之间传递数据是很常见的需求。界面传值有多种方式,如使用属性赋值、代理...
使用`synchronized`关键字保证线程安全,但是效率较低,因为每次获取实例都需要进行同步。 ```java public class Singleton { private static Singleton instance; private Singleton() {} public static ...
在这个“iOS单利定时器demo”中,我们将会探讨如何使用单例来管理定时器(Timer),从而实现对多个定时器的统一控制和管理。 首先,我们要了解什么是iOS中的定时器(NSTimer)。NSTimer是Foundation框架的一部分,...
1. **线程安全**:在多线程环境中,确保单例的初始化是线程安全的,避免竞态条件。Swift的静态属性已经保证了线程安全,但在其他语言中可能需要额外处理。 2. **生命周期管理**:由于单例生命周期与应用程序相同,...