1. 程式人生 > >JAVA多執行緒——共享變數

JAVA多執行緒——共享變數

【轉載】Java多執行緒程式設計:變數共享分析(Thread) 原部落格網址:https://www.cnblogs.com/xudong-bupt/archive/2013/05/22/3087864.html

今天看到java的多執行緒,感到十分激動,之前就在python中使用過多執行緒和多程序,十分強大,但是對於其中的理論卻並不是十分理解,因此希望藉此機會能夠使得理論知識有所長進。 首先程序和執行緒是兩個概念,一個程序就是一段靜態的程式碼,我的理解就是一次從頭到尾的程式碼的執行,開啟windows的工作管理員就能感到程序欄,每一個application都是一個程序,windows就是多程序執行的。而執行緒是一個更小的單位,一個程序中國可以很多個執行緒,而且執行緒間是可以共享變數,進行資料互動的,所以我的理解是執行緒其實不是獨立的,是彼此間有交流的,而程序則就是真正的獨立的一個任務階段了。今天看到唐大仕老師的java程式設計一書的P214的多執行緒程式碼的例子感到疑惑,為什麼共享了一個物件,而部分變數是共享的部分確實獨立的,看了本文終於理解,臨時變數是不共享的,因為一個執行緒有一個獨立的記憶體,而臨時變數是線上程建立後建立的,臨時變數存在於各個執行緒的記憶體之中,因此也是獨立的,而共享變數則用的是這個變數的記憶體,修改後則這個記憶體中的值修改了,就是做到了真正的共享。 以下便是轉載的部落格原文。 在編寫多執行緒程式時,最重要的就是搞清楚哪些變數是共享的,哪些變數是不共享的。也就是要分析清楚其中的原理呀。

因為最近要使用多執行緒就看了一些,對使用Thread類的子類建立執行緒的情況,總結如下:

1.方法體內部定義的區域性變數不共享

   這是因為方法內部定義的變數是在執行時動態生成的。每個執行緒都有一個自己的堆疊,用於儲存執行時的資料。

   最容易理解的就是遞迴呼叫時候,每次的入棧出棧操作。如下,每次呼叫時,變數aa都是在執行時堆疊上儲存的,方法結束變數也就釋放了。

複製程式碼
public int fib(int n)
{
    int aa;
    if(n==1 || n==0)
        
return 1; else return fib(n-1)*n; }
複製程式碼

2.成員變數

  2.1 程式碼示例

  成員變數需要看變數指向的是否為同一個物件。看下面的程式碼示例:

複製程式碼
package file2;
public class Analy {
    public static void main(String[] args) {
        Num i=new Num(0);    //新建物件,準備傳遞給執行緒
new OwnThread(i).start(); //新建執行緒,並啟動 new OwnThread(i).start(); //新建執行緒,並啟動 System.out.println("主執行緒中i的值變為了:"+i.i); //獲取目前物件i的數值 } }

class OwnThread extends Thread
{
Num id;
//申明物件,預設null,就是沒有指向任何實體
int sno; //申明int變數。因為系統預設初始化為0,所以應該是定義一個int變數
OwnThread(Num id)
{
this.id=id;
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> run()
{ 
    </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=0;i&lt;5;i++<span style="color: #000000;">)
    {
        </span><span style="color: #0000ff;">synchronized</span>(<span style="color: #0000ff;">this</span><span style="color: #000000;">)
        {
            sno</span>=id.i;    <span style="color: #008000;">//</span><span style="color: #008000;">儲存id.i的數值,到執行緒私有變數sno</span>
            id.i++<span style="color: #000000;">;
            </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
                Thread.sleep(</span>1<span style="color: #000000;">);
            } 
            </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {}
        }
        System.out.println(</span><span style="color: #0000ff;">this</span>.getName()+","+<span style="color: #000000;">sno);
    }
}

}

class Num //定義一個類
{
int i;
Num(
int i)
{
this.i=i;
}
}

複製程式碼

共享同一個物件,執行緒可以互動,執行結果:

 

2.2分析

  程式中主函式定義了Num物件的例項i,定義執行緒是傳遞到了Thread0和Thread1這樣三個變數就共享了一個Num物件的例項。而執行緒Thread0和執行緒Thread1又有自己的私有變數sno,可以用來儲存某一時刻的共享變數的數值。

   注意:(1)Java中判斷物件是否為同一個物件使用地址判斷的。地址相同就是同一個物件,上面的三個就是同一個物件。

        (2)如果把上面的例子中共享的物件例項用基本資料型別替換是不行的。因為基本資料型別程式會自動的用預設值初始化,也就是申明和定義時一起的。此時在mian函式中定義執行緒,傳遞的基本資料型別引數,只能是初始化執行緒中的另一個物件,而不是同一個物件。

3.總結

  總之,在多執行緒程式設計中,知道各個執行緒如何、怎麼樣共享資料是很重要的。

  如上面的程式,可以在主執行緒和其他兩個子執行緒之間共享一個物件,來實現他們之間的互動處理。

分類: java程式設計 好文要頂 關注我 收藏該文 旭東的部落格
關注 - 13
粉絲 - 372 +加關注 1 0 « 上一篇: Java中Object的輸出問題
» 下一篇: C++函式物件
	</div>
	<p class="postfoot">
		posted on <span id="post-date">2013-05-22 21:16</span> <a href="https://www.cnblogs.com/xudong-bupt/">旭東的部落格</a> 閱讀(<span id="post_view_count">30660</span>) 評論(<span id="post_comment_count">3</span>)  <a href="https://i.cnblogs.com/EditPosts.aspx?postid=3087864" rel="nofollow">編輯</a> <a href="#" onclick="AddToWz(3087864);return false;">收藏</a>
	</p>
</div>
<script type="text/javascript">var allowComments=true,cb_blogId=134009,cb_entryId=3087864,cb_blogApp=currentBlogApp,cb_blogUserGuid='10bd0daf-3b2b-e211-aa8f-842b2b196315',cb_entryCreatedDate='2013/5/22 21:16:00';loadViewCount(cb_entryId);var cb_postType=1;</script>

</div><a name="!comments"></a><div id="blog-comments-placeholder"><div id="comments_pager_top"></div>

評論

		<div class="post">
			<h2>
				<a href="#3402726" class="layer">#1樓</a><a name="3402726" id="comment_anchor_3402726"></a>
				&nbsp;&nbsp;<span class="comment_actions"></span>
			</h2>
			<div id="comment_body_3402726" class="blog_comment_body">多執行幾遍你會發現:<br>主執行緒中i的值變為了:0<br><b>Thread-0,0<br>Thread-1,0</b><br>Thread-1,3<br>Thread-0,2<br>Thread-0,5<br>Thread-1,4<br>Thread-1,7<br>Thread-0,6<br>Thread-1,8<br>Thread-0,9</div><div class="comment_vote"><a href="javascript:void(0);" class="comment_digg" onclick="return voteComment(3402726,'Digg',this)">支援(0)</a><a href="javascript:void(0);" class="comment_bury" onclick="return voteComment(3402726,'Bury',this)">反對(0)</a></div>
			<div class="postfoot">
				 <span class="comment_date">2016-04-07 19:37</span> | <a id="a_comment_author_3402726" href="https://www.cnblogs.com/lets-go/" target="_blank">深l度z</a> <a href="http://msg.cnblogs.com/send/%E6%B7%B1l%E5%BA%A6z" title="傳送站內短訊息" class="sendMsg2This">&nbsp;</a>
			</div>
		</div>
	
		<div class="post">
			<h2>
				<a href="#3519537" class="layer">#2樓</a><a name="3519537" id="comment_anchor_3519537"></a>
				&nbsp;&nbsp;<span class="comment_actions"></span>
			</h2>
			<div id="comment_body_3519537" class="blog_comment_body">博主你好,幾個執行緒使用 ThreadLocal set 同一個物件,為什麼就可以做到變數不共享呢?那也是同一個物件啊</div><div class="comment_vote"><a href="javascript:void(0);" class="comment_digg" onclick="return voteComment(3519537,'Digg',this)">支援(0)</a><a href="javascript:void(0);" class="comment_bury" onclick="return voteComment(3519537,'Bury',this)">反對(0)</a></div><span id="comment_3519537_avatar" style="display:none;">http://pic.cnblogs.com/face/924937/20180923162243.png</span>
			<div class="postfoot">
				 <span class="comment_date">2016-09-26 11:49</span> | <a id="a_comment_author_3519537" href="https://www.cnblogs.com/xmsx/" target="_blank">JavaRecorder</a> <a href="http://msg.cnblogs.com/send/JavaRecorder" title="傳送站內短訊息" class="sendMsg2This">&nbsp;</a>
			</div>
		</div>
	
		<div class="post">
			<h2>
				<a href="#3683468" class="layer">#3樓</a><a name="3683468" id="comment_anchor_3683468"></a><span id="comment-maxId" style="display:none;">3683468</span><span id="comment-maxDate" style="display:none;">2017/5/4 16:32:23</span>
				&nbsp;&nbsp;<span class="comment_actions"></span>
			</h2>
			<div id="comment_body_3683468" class="blog_comment_body"><a href="#3519537" title="檢視所回覆的評論" onclick="commentManager.renderComments(0,50,3519537);">@</a>

Vampire_x
這個問題,就是ThreadLocal的機制問題,ThreadLocat中有個Map 把當前執行緒和例項物件 繫結;。。這樣就相對獨立的固定到每一個執行緒中,具體的查查 ThreadLocal吧

支援(0) 反對(0) http://pic.cnblogs.com/face/902820/20160324120738.png

2017-05-04 16:32 | junyi5257