1. 程式人生 > >Spring中Singleton模式的執行緒安全

Spring中Singleton模式的執行緒安全

不知道哪裡的文章,總結性還是比較好的。但是程式碼凌亂,有的還沒有圖。如果找到原文了可以進行替換!

spring中的單例


spring中管理的bean例項預設情況下是單例的[sigleton型別],就還有prototype型別
按其作用域來講有sigleton(單例),prototype(原型),request,session,global session。


spring中的單例與設計模式裡面的單例略有不同
,設計模式的單例是在整個應用中只有一個例項,而spring中的單例是在一個IoC容器中就只有一個例項。

spring中的單例也不會影響應用的併發訪問,【不會出現各個執行緒之間的等待問題,或是死鎖問題】。

大多數時候客戶端都在訪問我們應用中的業務物件,為了減少併發控制,在這個時候我們不應該在業務物件中設定那些容易造成出錯的成員變數(成員變數的解決方式:1、方法的引數區域性變數(相當於new),2、threadlocal/2、設定bean的scope=prototype),在併發訪問時候這些成員變數將會是併發執行緒中的共享物件,那麼這個時候就會出現意外情況。

引出兩個問題(spring中併發所要考慮的)

先進行總結:

我們知道在一般情況下,只有無狀態的Bean才可以在多執行緒環境下共享,在Spring中,絕大部分Bean都可以宣告為singleton作用域。
那麼對於有狀態的bean呢?Spring對一些(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非執行緒安全狀態的bean採用ThreadLocal進行處理,讓它們也成為執行緒安全的狀態,因此有狀態的Bean就可以在多執行緒中共享了。


如果用有狀態的bean,也可以使用用prototype模式,每次在注入的時候就重新建立一個bean,在多執行緒中互不影響。

下面是分析的過程————

1、我們的Eic-server的所有的業務物件中的成員變數如,在Dao中的xxxDao,或controller中的xxxService,都會被多個執行緒共享,那麼這些物件不會出現同步問題嗎,比如會造成資料庫的插入,更新異常?

2、我們的實體bean,從客戶端傳遞到後臺的controller-->service-->Dao,這一個流程中,他們這些物件都是單例的,那麼這些單例的物件在處理我們的傳遞到後臺的實體bean不會出問題嗎?(實體bean在多執行緒中的解決方案)


答:[實體bean不是單例的],並沒有交給spring來管理,每次我們都手動的New出來的【如EMakeType et = new EMakeType();】,所以即使是那些處理我們提交資料的業務處理類是被多執行緒共享的,但是他們處理的資料並不是共享的,資料時每一個執行緒都有自己的一份,所以在資料這個方面是不會出現執行緒同步方面的問題的。

(在這裡補充下自己在專案開發中對於實體bean在多執行緒中的處理:1。對於實體bean一般通過方法引數的的形式傳遞(引數是區域性變數),所以多執行緒之間不會有影響。2.有的地方對於有狀態的bean直接使用prototype原型模式來進行解決。3.對於使用bean的地方可以通過new的方式來建立)

但是那些在Dao中的xxxDao,或controller中的xxxService,這些物件都是單例那麼就不會出現執行緒同步的問題。話又說回來,這些物件雖然會被多個程序併發訪問,可我們訪問的是他們裡面的方法,這些類裡面通常不會含有成員變數,那個Dao裡面的ibatisDao是框架裡面封裝好的,已經被測試,不會出現執行緒同步問題了。所以出問題的地方就是我們自己系統裡面的業務物件,所以我們一定要注意這些業務物件裡面千萬不能要獨立成員變數,否則會出錯。


所以我們在應用中的業務物件如下例子;
controller中的成員變數List和paperService:
public class TestPaperController extends BaseController {
private static final int List = 0;
@Autowired
@Qualifier("papersService")
private TestPaperService papersService ;
public Page queryPaper(int pageSize, int page,TestPaper paper) throws EicException{
  RowSelection localRowSelection = getRowSelection(pageSize, page);
  List<TestPaper> paperList = papersService.queryPaper(paper,localRowSelection);
  Page localPage = new Page(page, localRowSelection.getTotalRows(),
    paperList);
  return localPage;
  
}


service裡面的成員變數ibatisEntityDao:

@SuppressWarnings("unchecked")
@Service("papersService")
@Transactional(rollbackFor = { Exception.class })
public class TestPaperServiceImpl implements TestPaperService {
@Autowired
@Qualifier("ibatisEntityDao")
private IbatisEntityDao ibatisEntityDao;
private static final String NAMESPACE_TESTPAPER = "com.its.exam.testpaper.model.TestPaper";
private static final String BO_NAME[] = { "試卷倉庫" };
private static final String BO_NAME2[] = { "試卷配置試題" };
private static final String BO_NAME1[] = { "試卷試題型別" };
private static final String NAMESPACE_TESTQUESTION="com.its.exam.testpaper.model.TestQuestion";
public List<TestPaper> queryPaper(TestPaper paper,RowSelection paramRowSelection) throws EicException{
  try {

   return (List<TestPaper>) ibatisEntityDao.queryForListWithPage(
    NAMESPACE_TESTPAPER, "queryPaper", paper,paramRowSelection);
  } catch (Exception exception) {
   exception.printStackTrace();
   throw new EicException(exception, "eic", "0001", BO_NAME);
  }

}

由上面可以看出,雖然我們這個應用裡面含有成員變數,但是並不會出現執行緒同步方面的問題,因為,controller裡面的成員變數private TestPaperService papersService 之所以會成為成員變數,我們的目的是注入,將其例項化進而訪問裡面的方法,private static final int List = 0;是final的不會被改變。
service裡面的private IbatisEntityDao ibatisEntityDao;是框架本身的執行緒同步問題已解決【其解決方案很有可能就是使用ThreadLocal,見下面】。



這下面的bean 一個是通過BeanFactory getBean得到,一個是業務物件testPaper.getClass()得到,通過不同客戶端的瀏覽器訪問,可得到下面結論,
springIoC容器管理的bean就是單例,因為不同的訪問均得到相同的物件【在應用開啟的狀態下,不重新啟動應用下,即在同一次的應用執行中】

-------------------------spring 中的sigleton ,這才是真正的整個應用下面就一個例項:class

com.its.exam.testpaper.service.impl.TestPaperServiceImpl$$EnhancerByCGLIB$$584b889d
-------------------------spring 中的sigleton ,這才是真正的整個應用下面就一個例項:class

com.its.exam.testpaper.service.impl.TestPaperServiceImpl$$EnhancerByCGLIB$$584b889d
-------------------------spring 中的sigleton ,這才是真正的整個應用下面就一個例項:class

com.its.exam.testpaper.service.impl.TestPaperServiceImpl$$EnhancerByCGLIB$$584b889d
-------------------------spring 中的sigleton ,這才是真正的整個應用下面就一個例項:class

com.its.exam.testpaper.service.impl.TestPaperServiceImpl$$EnhancerByCGLIB$$584b889d
spring無狀態的支援
Spring框架對單例的支援是採用單例登錄檔的方式進行實現的,詳見

spring有狀態的支援

至於spring如何實現那些個有狀態bean[如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder]的執行緒安全,即使用ThreadLocal實現的。如下原理:還可以參考網上這篇文章:“淺談Spring宣告式事務管理ThreadLocal和JDKProxy”。(???????)

下面是對ThreadLocal的講解:

當使用ThreadLocal維護變數(僅僅是變數,因為執行緒同步的問題就是成員變數的互斥訪問出問題——根源之所在)時,ThreadLocal為每個使用該變數的執行緒提供獨立的變數副本,所以每一個執行緒都可以獨立地改變自己的副本,而不會影響其它執行緒所對應的副本。

原理概念:為每一個使用該變數的執行緒都提供一個變數值的副本,是每一個執行緒都可以獨立地改變自己的副本,而不會和其它執行緒的副本衝突。從執行緒的角度看,就好像每一個執行緒都完全擁有該變數。【每個執行緒其實是改變的是自己執行緒的副本,而不是真正要改變的變數,所以效果就是每個執行緒都有自己的,“這其實就將共享變相為人人有份!”】

雖然使用ThreadLocal會帶來更多的記憶體開銷,但這點開銷是微不足道的。因為儲存在ThreadLocal中的物件,通常都是比較小的物件。

基本概念:為每一個使用該變數的執行緒都提供一個變數值的副本,是每一個執行緒都可以獨立地改變自己的副本,而不會和其它執行緒的副本衝突。從執行緒的角度看,就好像每一個執行緒都完全擁有該變數。

 它主要由四個方法組成initialValue(),get(),set(T),remove(),其中值得注意的是initialValue(),該方法是一個protected的方法,顯然是為了子類重寫而特意實現的。該方法返回當前執行緒在該執行緒區域性變數的初始值,這個方法是一個延遲呼叫方法,在一個執行緒第1次呼叫get()或者set(Object)時才執行,並且僅執行1次。ThreadLocal中的確實實現直接返回一個null: 舉例  ThreadLocal的原理

  ThreadLocal是如何做到為每一個執行緒維護變數的副本的呢?其實實現的思路很簡單,在ThreadLocal類中有一個Map,用於儲存每一個執行緒的變數的副本。比如下面的示例實現:

public class ThreadLocal{

			<span style="color:#FF0000;">private Map values = Collections.synchronizedMap(new HashMap());</span>
	
			public Object get() {
	
				Thread curThread = Thread.currentThread();
			
				Object o = values.get(curThread);
			
				if (o == null && !values.containsKey(curThread)){
	
					o = initialValue();
				
					values.put(curThread, o);
	
				}
	
				return o;
		  	}
	
			public void set(Object newValue){	
					values.put(Thread.currentThread(), newValue);
			}
	
			public Object initialValue(){
				return null;
		  	}

		}

  

使用方法:ThreadLocal 的使用


  使用方法一:

  Hibernate的文件時看到了關於使ThreadLocal管理多執行緒訪問的部分。具體程式碼如下

  
public static final ThreadLocal session = new ThreadLocal(); //使用ThreadLocal變數

	public static Session currentSession() {

		 Session s = (Session)session.get();
	
		//open a new session,if this session has none
	
		 if(s == null){
	
			 s = sessionFactory.openSession();
		
			 session.set(s);
		
		 }
	
		return s;
 	}



  我們逐行分析上面的程式碼

  1、初始化一個ThreadLocal物件,ThreadLocal有三個成員方法 get()、set()、initialvalue()。

    2、如果不初始化initialvalue,則initialvalue返回null。

  3、session的get根據當前執行緒返回其對應的執行緒內部變數,也就是我們需要的net.sf.hibernate.Session(相當於對應每個資料庫連線)。多執行緒情況下共享資料庫連結是不安全的。ThreadLocal保證了每個執行緒都有自己的session(資料庫連線)。

  5、如果是該執行緒是初次訪問,自然,s(資料庫連線)會是null,接著建立一個Session,具體就是行6。

  6、建立一個數據庫連線例項 s

  7、儲存該資料庫連線s到ThreadLocal中。

  8、如果當前執行緒已經訪問過資料庫了,則從session中get()就可以獲取該執行緒上次獲取過的連線例項。

  使用方法二

  當要給執行緒初始化一個特殊值時,需要自己實現ThreadLocal的子類並重寫該方法,通常使用一個內部匿名類對ThreadLocal進行子類化,EasyDBO中建立jdbc連線上下文就是這樣做的:

  
public class JDBCContext{

		private static Logger logger = Logger.getLogger(JDBCContext.class);

		private DataSource ds;

		protected Connection connection;

		private boolean isValid = true;

		private static ThreadLocal jdbcContext; //ThreadLocal變數

		private JDBCContext(DataSource ds){
			this.ds = ds;
			createConnection();
		}

		public static JDBCContext getJdbcContext(javax.sql.DataSource ds){

			if(jdbcContext==null)jdbcContext=new JDBCContextThreadLocal(ds); //new的建立,看下面的自定義方法
			JDBCContext context = (JDBCContext) jdbcContext.get();
			
			if (context == null) {
				context = new JDBCContext(ds);
			}
	
			return context;
		}

		private static class JDBCContextThreadLocal extends ThreadLocal{

			public javax.sql.DataSource ds;
	
			public JDBCContextThreadLocal(javax.sql.DataSource ds){
				this.ds=ds;
			}
	
			protected synchronized Object initialValue() {
				return new JDBCContext(ds);
			}
		}

	}


  簡單的實現版本

  程式碼清單1 SimpleThreadLocal
 
public class SimpleThreadLocal {
			
			private Map valueMap = Collections.synchronizedMap(new HashMap());

			public void set(Object newValue) {
				valueMap.put(Thread.currentThread(), newValue); //①鍵為執行緒物件,值為本執行緒的變數副本
			}

			public Object get() {
				Thread currentThread = Thread.currentThread();
				Object o = valueMap.get(currentThread); 	//②返回本執行緒對應的變數
	
				if (o == null && !valueMap.containsKey(currentThread)) {//③如果在Map中不存在,放到Map中儲存起來。
					o = initialValue();
					valueMap.put(currentThread, o);
				}
				
				return o;
			}

			public void remove() {
				valueMap.remove(Thread.currentThread());
			}

			public Object initialValue() {
				return null;
			}

		}
  雖然程式碼清單9‑3這個ThreadLocal實現版本顯得比較幼稚,但它和JDK所提供的ThreadLocal類在實現思路上是相近的。

ThreadLocal和synchronized之間的區別:

             在Java的多執行緒程式設計中,為保證多個執行緒對共享變數的安全訪問,通常會使用synchronized來保證同一時刻只有一個執行緒對共享變數進行操作。但在有些情況下,synchronized不能保證多執行緒對共享變數的正確讀寫。例如類有一個類變數,該類變數會被多個類方法讀寫,當多執行緒操作該類的例項物件時,如果執行緒對類變數有讀取、寫入操作就會發生類變數讀寫錯誤,即便是在類方法前加上synchronized也無效,因為同一個執行緒在兩次呼叫方法之間時鎖是被釋放的,這時其它執行緒可以訪問物件的類方法,讀取或修改類變數。這種情況下可以將類變數放到ThreadLocal型別的物件中,使變數在每個執行緒中都有獨立拷貝,不會出現一個執行緒讀取變數時而被另一個執行緒修改的現象。

  下面舉例說明:
  
public class QuerySvc {

		private String sql;

		private static ThreadLocal sqlHolder = new ThreadLocal();

		public QuerySvc() {

		}

		public void execute() {
			System.out.println("Thread " + Thread.currentThread().getId() +" Sql is " + sql);
	
			System.out.println("Thread " + Thread.currentThread().getId() +" Thread Local variable Sql is " + sqlHolder.get());
		}

		public String getSql() {
			return sql;
		}

		public void setSql(String sql) {
			this.sql = sql;
			sqlHolder.set(sql);
		}

	}



  為了說明多執行緒訪問對於類變數和ThreadLocal變數的影響,QuerySvc中分別設定了類變數sql和ThreadLocal變數,使用時先建立 QuerySvc的一個例項物件,然後產生多個執行緒,分別設定不同的sql例項物件,然後再呼叫execute方法,讀取sql的值,看是否是set方法中寫入的值。這種場景類似web應用中多個請求執行緒攜帶不同查詢條件對一個servlet例項的訪問,然後servlet呼叫業務物件,並傳入不同查詢條件,最後要保證每個請求得到的結果是對應的查詢條件的結果。

  使用QuerySvc的工作執行緒如下:

  public class Work extends Thread {

  private QuerySvc querySvc;

  private String sql;

  public Work(QuerySvc querySvc,String sql) {

  this.querySvc = querySvc;

  this.sql = sql;

  }

  public void run() {

  querySvc.setSql(sql);

  querySvc.execute();

  }

  }

  執行執行緒程式碼如下:

  QuerySvc qs = new QuerySvc();

  for (int k=0; k<10>

  String sql = "Select * from table where id =" + k;

  new Work(qs,sql).start();

  }

  先建立一個QuerySvc例項物件,然後建立若干執行緒來呼叫QuerySvc的set和execute方法,每個執行緒傳入的sql都不一樣,從執行結果可以看出sql變數中值不能保證在execute中值和set設定的值一樣,在 web應用中就表現為一個使用者查詢的結果不是自己的查詢條件返回的結果,而是另一個使用者查詢條件的結果;而ThreadLocal中的值總是和set中設定的值一樣,這樣通過使用ThreadLocal獲得了執行緒安全性。

總結比較:

  如果一個物件要被多個執行緒訪問,而該物件存在類變數被不同類方法讀寫,為獲得執行緒安全,可以用ThreadLocal來替代類變數。

       同步機制的比較  ThreadLocal和執行緒同步機制相比有什麼優勢呢?ThreadLocal和執行緒同步機制都是為了解決多執行緒中相同變數的訪問衝突問題。

  在同步機制中,通過物件的鎖機制保證同一時間只有一個執行緒訪問變數。這時該變數是多個執行緒共享的,使用同步機制要求程式慎密地分析什麼時候對變數進行讀寫,什麼時候需要鎖定某個物件,什麼時候釋放物件鎖等繁雜的問題,程式設計和編寫難度相對較大。

  而ThreadLocal則從另一個角度來解決多執行緒的併發訪問。ThreadLocal會為每一個執行緒提供一個獨立的變數副本,從而隔離了多個執行緒對資料的訪問衝突。因為每一個執行緒都擁有自己的變數副本,從而也就沒有必要對該變數進行同步了。ThreadLocal提供了執行緒安全的共享物件,在編寫多執行緒程式碼時,可以把不安全的變數封裝進ThreadLocal。

  由於ThreadLocal中可以持有任何型別的物件,低版本JDK所提供的get()返回的是Object物件,需要強制型別轉換。但JDK 5.0通過泛型很好的解決了這個問題,在一定程度地簡化ThreadLocal的使用,程式碼清單 9 2就使用了JDK 5.0新的ThreadLocal版本。

  概括起來說,對於多執行緒資源共享的問題,同步機制採用了“以時間換空間”的方式,而ThreadLocal採用了“以空間換時間”的方式。前者僅提供一份變數,讓不同的執行緒排隊訪問,而後者為每一個執行緒都提供了一份變數,因此可以同時訪問而互不影響。

  Spring使用ThreadLocal解決執行緒安全問題

  我們知道在一般情況下,只有無狀態的Bean才可以在多執行緒環境下共享,在Spring中,絕大部分Bean都可以宣告為singleton作用域。就是因為Spring對一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非執行緒安全狀態採用ThreadLocal進行處理,讓它們也成為執行緒安全的狀態,因為有狀態的Bean就可以在多執行緒中共享了。(賊重要)

  一般的Web應用劃分為展現層、服務層和持久層三個層次,在不同的層中編寫對應的邏輯,下層通過介面向上層開放功能呼叫。在一般情況下,從接收請求到返回響應所經過的所有程式呼叫都同屬於一個執行緒,如圖9‑2所示:

  這樣你就可以根據需要,將一些非執行緒安全的變數以ThreadLocal存放,在同一次請求響應的呼叫執行緒中,所有關聯的物件引用到的都是同一個變數。

  下面的例項能夠體現Spring對有狀態Bean的改造思路:

  程式碼清單3 TopicDao:非執行緒安全

  public class TopicDao {

  private Connection conn;①一個非執行緒安全的變數

  public void addTopic(){

  Statement stat = conn.createStatement();②引用非執行緒安全變數

  …

  }

  }

  由於①處的conn是成員變數,因為addTopic()方法是非執行緒安全的,必須在使用時建立一個新TopicDao例項(非singleton)。下面使用ThreadLocal對conn這個非執行緒安全的“狀態”進行改造:

  程式碼清單4 TopicDao:執行緒安全

  import java.sql.Connection;

  import java.sql.Statement;

  public class TopicDao {

  ①使用ThreadLocal儲存Connection變數

  private static ThreadLocal connThreadLocal = new ThreadLocal();

  public static Connection getConnection(){

  ②如果connThreadLocal沒有本執行緒對應的Connection建立一個新的Connection,

  並將其儲存到執行緒本地變數中。

  if (connThreadLocal. get() == null) {

  Connection conn = ConnectionManager.getConnection();

  connThreadLocal.set(conn);

  return conn;

  }else{

  return connThreadLocal. get();③直接返回執行緒本地變數

  }

  }

  public void addTopic() {

  ④從ThreadLocal中獲取執行緒對應的Connection

  Statement stat = getConnection().createStatement();

  }

  }

  不同的執行緒在使用TopicDao時,先判斷connThreadLocal.是否是null,如果是null,則說明當前執行緒還沒有對應的Connection物件,這時建立一個Connection物件並新增到本地執行緒變數中;如果不為null,則說明當前的執行緒已經擁有了Connection物件,直接使用就可以了。這樣,就保證了不同的執行緒使用執行緒相關的Connection,而不會使用其它執行緒的Connection。因此,這個TopicDao就可以做到singleton共享了。

  當然,這個例子本身很粗糙,將Connection的ThreadLocal直接放在DAO只能做到本DAO的多個方法共享Connection時不發生執行緒安全問題,但無法和其它DAO共用同一個Connection,要做到同一事務多DAO共享同一Connection,必須在一個共同的外部類使用ThreadLocal儲存Connection。

     小結  ThreadLocal是解決執行緒安全問題一個很好的思路,它通過為每個執行緒提供一個獨立的變數副本解決了變數併發訪問的衝突問題。在很多情況下,ThreadLocal比直接使用synchronized同步機制解決執行緒安全問題更簡單,更方便,且結果程式擁有更高的併發性。
結論就是:在spring管理【ThreadLocal管理的類變數,他也僅僅是在管理變數而已】的,要訪問執行緒不安全的物件中的變數的時候都會將原來的物件copy一份,進而訪問這個copy

版本,所以從來就沒有機會訪問原來的物件,反而這個原來應該被訪問的物件倒是成了閒置、冗餘的物件了。

相關推薦

SpringSingleton模式執行安全

不知道哪裡的文章,總結性還是比較好的。但是程式碼凌亂,有的還沒有圖。如果找到原文了可以進行替換! spring中的單例 spring中管理的bean例項預設情況下是單例的[sigleton型別],就還有prototype型別 按其作用域來講有sigleton(單例),pro

Java 單例模式執行安全問題

Java 單例模式執行緒安全問題  更新時間:2017年09月14日 11:30:42   作者:flycw    我要評論   這篇文章主要介紹了Java 單例模式執行緒安全問題的相關資料,希望通過本文大家能瞭解掌握單例模式中

HibernateSessionFactory是執行安全的嗎?Session是執行安全的嗎(兩個執行能夠共享同一個Session嗎)?

Hibernate中SessionFactory是執行緒安全的嗎?Session是執行緒安全的嗎(兩個執行緒能夠共享同一個Session嗎)? SessionFactory對應Hibernate的一個數據儲存的概念,它是執行緒安全的,可以被多個執行緒併發訪問。 Sessio

spring使用多執行ThreadPoolTaskExecutor

業務需要,在進行更新的時候會執行一系列操作,或者說更新時會有一個通知.但是沒有使用訊息佇列.所以我想用多執行緒來實現這個功能.最開始沒有使用執行緒池.使用的是內部類的形式實現,程式碼為: /** * create by : * description: 開啟接單

面試題剖析:單例設計模式執行安全問題

本文作者:黃海燕,叩丁狼高階講師。原創文章,轉載請註明出處。 1. volatile 關鍵字 1.1 volatile 關鍵字作用: 在百度百科擷取的描述如下: 叩丁狼教育.png 說明volatile 關鍵字作用作用有兩點: 防止指令重

Servlet如何解決執行安全

造成執行緒安全原因:多個執行緒併發訪問同一份資源(只有一個Servlet物件) 方法一:讓自己的Servlet類實現javax.servlet.SingleThreadModel介面,同時只能讓一個執

Spring-利用ThreadLocal解決執行安全問題

ThreadLocal是什麼 ThreadLocal,顧名思義,它不是一個執行緒,而是執行緒的一個本地化物件。當工作於多執行緒中的物件使用ThreadLocal維護變數時,ThreadLocal為每個使用該變數的執行緒分配一個獨立的變數副本。所以每一個執行緒都可以獨立地改

java單例模式執行安全

關於單例模式的文章,其實網上早就已經氾濫了。但一個小小的單例,裡面卻是有著許多的變化。網上的文章大多也是提到了其中的一個或幾個點,很少有比較全面且脈絡清晰的文章,於是,我便萌生了寫這篇文章的念頭。企圖把這個單例說透,說深入。但願我不會做的太差。   首先來看一個典型的實

spring的多執行aop方法攔截

日常開發中,常用spring的aop機制來攔截方法,記點日誌、執行結果、方法執行時間啥的,很是方便,比如下面這樣:(以spring-boot專案為例) 一、先定義一個Aspect import org.aspectj.lang.ProceedingJoinPoint; import org.aspe

Spring 使用ThreadLocal 解決執行安全問題

Spring 中的 一些bean, 如 RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder 等非執行緒安全的“狀態性物件”採用ThreadLocal進行封裝,讓他們也稱為執行緒安

Spring-利用ThreadLocal解決執行安全問題(多執行併發登入)

ThreadLocal是什麼ThreadLocal,顧名思義,它不是一個執行緒,而是執行緒的一個本地化物件。當工作於多執行緒中的物件使用ThreadLocal維護變數時,ThreadLocal為每個使用該變數的執行緒分配一個獨立的變數副本。所以每一個執行緒都可以獨立地改變自己

Java哪些是執行安全的容器?

同步容器類:使用了synchronized 1.Vector 2.HashTable 併發容器: 3.ConcurrentHashMap:分段 4.CopyOnWriteArrayList:寫時複製 5.CopyOnWriteArraySet:寫時複製 Queue: 6.Concur

spring單例、執行安全、事務等疑惑 收集

文章轉載於: http://haidaoqi3630.iteye.com/blog/1920944 http://www.cnblogs.com/davidwang456/p/3832949.html Spring的事務傳遞機制: PROPAGATION_REQUIRED 如

設計模式之單例模式(執行安全)

可以說單例模式是所有設計模式中最簡單的一種。 單例模式就是說系統中對於某類的只能有一個物件,不可能出來第二個。 單例模式也是23中設計模式中在面試時少數幾個會要求寫程式碼的模式之一。主要考察的是多執行緒下面單例模式的執行緒安全性問題。 1.多執行緒安全單例模式例項一(不使用同步鎖) 1 public c

Spring MVC Controller的執行安全

問題: spring mvc controller執行緒安全嗎? 引申servlet及struts1/2的Action執行緒安全嗎? 知識點: 例項變數和類變數(靜態變數) 類&單例項&多例項(如何知道一個類有多少個例項) 執行緒名稱&執行緒

spring單例模式執行安全問題

@RequestMapping(value = "getPsdbData", method = RequestMethod.POST) public Map<String, Object> getPsdbData(String key,HttpServletRequest reques

Qt實現執行安全的單例模式

之前專案中用到單例模式,用的是執行緒不安全的,這次專案用到了多執行緒,所以想到實現一個執行緒安全的單例模式。經過查詢資料,發現Qt本身有自己的執行緒安全單例模式實現方式。 Q_GLOBAL_STATIC巨集 使用方法:MonitorWindow.h #ifndef MONITORW

Java執行安全的單例模式

Java中執行緒安全的單例 深入研究Servlet執行緒安全性問題 來源:網路整理 作者:2017年12月01日 14:03 0 分享 訂閱 關鍵詞:Servlet執行緒     Servlet(Server Applet)是Java Servle

python單例模式執行安全問題

看了好多文章都是java實現的,特此寫一篇python的。 這個問題的兩種解決方案: 1.最簡單粗暴的就是在系統中先生成一個單例,就不存線上程安全問題了 2.用雙重同步鎖去實現,一把鎖加外面,一把鎖加里面: class Singleton(object): __instance

單例模式的懶漢式及其執行安全問題

先看程式碼: package com.roocon.thread.t5; public class Singleton2 { private Singleton2(){ } private static Singleton2 instan