<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>中文 &#187; phinecos</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/phinecos/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sat, 26 May 2012 06:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>浅谈Java多线程的同步问题</title>
		<link>http://software.intel.com/zh-cn/blogs/2010/03/19/java-2/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2010/03/19/java-2/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 06:47:03 +0000</pubDate>
		<dc:creator>phinecos</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[多线程]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2010/03/19/java-2/</guid>
		<description><![CDATA[多线程的同步依靠的是对象锁机制，synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。 下面以一个简单的实例来进行对比分析。实例要完成的工作非常简单，就是创建10个线程，每个线程都打印从0到99这100个数字，我们希望线程之间不会出现交叉乱序打印，而是顺序地打印。 先来看第一段代码，这里我们在run()方法中加入了synchronized关键字，希望能对run方法进行互斥访问，但结果并不如我们希望那样，这是因为这里synchronized锁住的是this对象，即当前运行线程对象本身。代码中创建了10个线程，而每个线程都持有this对象的对象锁，这不能实现线程的同步。 代码 package com.vista; class MyThread implements java.lang.Runnable { private int threadId; public MyThread(int id) { this.threadId = id; } @Override public synchronized void run() { for (int i = 0; i &#60; 100; ++i) { System.out.println("Thread ID: " + this.threadId + " : " + i); } } } public class ThreadDemo [...]]]></description>
			<content:encoded><![CDATA[<p>多线程的同步依靠的是对象锁机制，synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。</p>
<p>下面以一个简单的实例来进行对比分析。实例要完成的工作非常简单，就是创建10个线程，每个线程都打印从0到99这100个数字，我们希望线程之间不会出现交叉乱序打印，而是顺序地打印。</p>
<p>先来看第一段代码，这里我们在run()方法中加入了synchronized关键字，希望能对run方法进行互斥访问，但结果并不如我们希望那样，这是因为这里synchronized锁住的是this对象，即当前运行线程对象本身。代码中创建了10个线程，而每个线程都持有this对象的对象锁，这不能实现线程的同步。</p>
<p>代码<br />
package com.vista;</p>
<p>class MyThread implements java.lang.Runnable<br />
{<br />
private int threadId;</p>
<p>public MyThread(int id)<br />
{<br />
this.threadId = id;<br />
}<br />
@Override<br />
public synchronized void run()<br />
{<br />
for (int i = 0; i &lt; 100; ++i)<br />
{<br />
System.out.println("Thread ID: " + this.threadId + " : " + i);<br />
}<br />
}<br />
}<br />
public class ThreadDemo<br />
{<br />
/**<br />
* @param args<br />
* @throws InterruptedException<br />
*/<br />
public static void main(String[] args) throws InterruptedException<br />
{<br />
for (int i = 0; i &lt; 10; ++i)<br />
{<br />
new Thread(new MyThread(i)).start();<br />
Thread.sleep(1);<br />
}<br />
}<br />
}</p>
<p>从上述代码段可以得知，要想实现线程的同步，则这些线程必须去竞争一个唯一的共享的对象锁。</p>
<p>基于这种思想，我们将第一段代码修改如下所示，在创建启动线程之前，先创建一个线程之间竞争使用的Object对象，然后将这个Object对象的引用传递给每一个线程对象的lock成员变量。这样一来，每个线程的lock成员都指向同一个Object对象。我们在run方法中，对lock对象使用synchronzied块进行局部封锁，这样就可以让线程去竞争这个唯一的共享的对象锁，从而实现同步。</p>
<p>代码<br />
package com.vista;</p>
<p>class MyThread implements java.lang.Runnable<br />
{<br />
private int threadId;<br />
private Object lock;<br />
public MyThread(int id, Object obj)<br />
{<br />
this.threadId = id;<br />
this.lock = obj;<br />
}<br />
@Override<br />
public void run()<br />
{<br />
synchronized(lock)<br />
{<br />
for (int i = 0; i &lt; 100; ++i)<br />
{<br />
System.out.println("Thread ID: " + this.threadId + " : " + i);<br />
}<br />
}<br />
}<br />
}<br />
public class ThreadDemo<br />
{<br />
/**<br />
* @param args<br />
* @throws InterruptedException<br />
*/<br />
public static void main(String[] args) throws InterruptedException<br />
{<br />
Object obj = new Object();<br />
for (int i = 0; i &lt; 10; ++i)<br />
{<br />
new Thread(new MyThread(i, obj)).start();<br />
Thread.sleep(1);<br />
}<br />
}<br />
}</p>
<p>从第二段代码可知，同步的关键是多个线程对象竞争同一个共享资源即可，上面的代码中是通过外部创建共享资源，然后传递到线程中来实现。我们也可以利用类成员变量被所有类的实例所共享这一特性，因此可以将lock用静态成员对象来实现，代码如下所示：</p>
<p>代码<br />
package com.vista;</p>
<p>class MyThread implements java.lang.Runnable<br />
{<br />
private int threadId;<br />
private static Object lock = new Object();<br />
public MyThread(int id)<br />
{<br />
this.threadId = id;<br />
}<br />
@Override<br />
public void run()<br />
{<br />
synchronized(lock)<br />
{<br />
for (int i = 0; i &lt; 100; ++i)<br />
{<br />
System.out.println("Thread ID: " + this.threadId + " : " + i);<br />
}<br />
}<br />
}<br />
}<br />
public class ThreadDemo<br />
{<br />
/**<br />
* @param args<br />
* @throws InterruptedException<br />
*/<br />
public static void main(String[] args) throws InterruptedException<br />
{<br />
for (int i = 0; i &lt; 10; ++i)<br />
{<br />
new Thread(new MyThread(i)).start();<br />
Thread.sleep(1);<br />
}<br />
}<br />
}</p>
<p>再来看第一段代码，实例方法中加入sychronized关键字封锁的是this对象本身，而在静态方法中加入sychronized关键字封锁的就是类本身。静态方法是所有类实例对象所共享的，因此线程对象在访问此静态方法时是互斥访问的，从而可以实现线程的同步，代码如下所示：</p>
<p>代码<br />
package com.vista;</p>
<p>class MyThread implements java.lang.Runnable<br />
{<br />
private int threadId;</p>
<p>public MyThread(int id)<br />
{<br />
this.threadId = id;<br />
}<br />
@Override<br />
public void run()<br />
{<br />
taskHandler(this.threadId);<br />
}<br />
private static synchronized void taskHandler(int threadId)<br />
{<br />
for (int i = 0; i &lt; 100; ++i)<br />
{<br />
System.out.println("Thread ID: " + threadId + " : " + i);<br />
}<br />
}<br />
}<br />
public class ThreadDemo<br />
{<br />
/**<br />
* @param args<br />
* @throws InterruptedException<br />
*/<br />
public static void main(String[] args) throws InterruptedException<br />
{<br />
for (int i = 0; i &lt; 10; ++i)<br />
{<br />
new Thread(new MyThread(i)).start();<br />
Thread.sleep(1);<br />
}<br />
}<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2010/03/19/java-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

