第55章
大b:“在多线程模式下,惰性初始化会使多个线程同时初始化该单体,造成一个jvm中多个单例类型的实例,如果这个单例类型的成员变量在运行过程中发生变化,会造成多个单例类型实例的不一致。”
小a:“那应该怎么办?”
大b:“加个同步修饰符:publicstaticsynchronizedsingletongetinstance()。这样就保证了线程的安全性。这种处理方式虽然引入了同步代码,但是因为这段同步代码只会在最开始的时候执行一次或多次,所以对整个系统的性能不会有影响。”
小a:“在更新属性的时候,会造成属性的读写不一致。那应该怎么处理?”
大b:“1、读者/写者的处理方式。设置一个读计数器,每次读取信息前,将计数器加1,读完后将计数器减1。使用notifyall()解除在该对象上调用wait的线程阻塞状态。只有在读计数器为0时,才能更新数据,同时调用wait()方法要阻塞所有读属性的调用。2、采用‘影子实例’的办法。具体说,就是在更新属性时,直接生成另一个单例对象实例,这个新生成的单例对象实例将从数据库,文件或程序中读取最新的信息;然后将这些信息直接赋值给旧单例对象的属性。”
小a:“嘿嘿!师兄,能不能举例来看一下啊?”
大b:“好的。”
例子:
publicclassglobalconfig{
privatestaticglobalconfiginstance;
privatevectorproperties=null;
privatebooleanisupdating=false;
privateintreadcount=0;
privateglobalconfig(){
//loadconfigurationinformationfromdborfile
//setvaluesforproperties
}
privatestaticsynchronizedvoidsyncinit(){
if(instance……null){
instance=newglobalconfig();
}
}
publicstaticglobalconfiggetinstance(){
if(instance……null){
syncinit();
}
returninstance;
}
publicsynchronizedvoidupdate(stringpdata){
syncupdatein();
//updateproperties
}
privatesynchronizedvoidsyncupdatein(){
while(readcount>0){
try{
wait();
}catch(exceptione){
}
}
}
privatesynchronizedvoidsyncreadin(){
readcount++;
}
privatesynchronizedvoidsyncreadout(){
readcount——;
notifyall();
}
publicvectorgetproperties(){
syncreadin();
//processdata
syncreadout();
returnproperties;
}
}
publicclassglobalconfig{
privatestaticglobalconfiginstance;
privatevectorproperties=null;
privatebooleanisupdating=false;
privateintreadcount=0;
privateglobalconfig(){
//loadconfigurationinformationfromdborfile
//setvaluesforproperties
}
privatestaticsynchronizedvoidsyncinit(){
if(instance……null){
instance=newglobalconfig();
}
}
publicstaticglobalconfiggetinstance(){
if(instance……null){
syncinit();
}
returninstance;
}
publicsynchronizedvoidupdate(stringpdata){
syncupdatein();
//updateproperties
}
privatesynchronizedvoidsyncupdatein(){
while(readcount>0){
try{
wait();
}catch(exceptione){
}
}
}
privatesynchronizedvoidsyncreadin(){
readcount++;
}
privatesynchronizedvoidsyncreadout(){
readcount——;
notifyall();
}
publicvectorgetproperties(){
syncreadin();
//processdata
syncreadout();
returnproperties;
}
}