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编程
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吧

http://pic.cnblogs.com/face/902820/20160324120738.png

2017-05-04 16:32 | junyi5257  

猜你喜欢

转载自blog.csdn.net/qq_39805362/article/details/83988412