⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threads.doc.html

📁 Jvm 规范说明。The Java Virtual Machine was designed to support the Java programming language. Some concep
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<a name="23969"></a>
The total set of operations may be pictured as follows:<br><br><img src="Threads.doc.anc1.gif">
<br><br><p>
<a name="23970"></a>
The <i>lock</i> and <i>unlock</i> operations provide further constraints on the order of operations by the main memory; the <i>lock</i> operation by one thread cannot occur between the <i>lock</i> and <i>unlock</i> operations of the other thread. Moreover, the <i>unlock</i> operations require that the <i>store</i> and <i>write</i> operations occur. It follows that only two sequences are possible:<p>
<ul><a name="23971"></a>
<li><i>write</i> <code>a</code><code><img src="chars/arrwrite.gif"></code><i>read</i> <code>a</code>, <i>read</i> <code>b</code><code><img src="chars/arrwrite.gif"></code><i>write</i> <code>b</code> (then <code>ha=2</code>, <code>hb=2</code>, <code>ma=2</code>, <code>mb=2</code>,<code> ya=2</code>, <code>yb=2</code>)
<a name="23972"></a>
<li><i>read</i> <code>a</code><code><img src="chars/arrwrite.gif"></code><i>write</i> <code>a</code>, <i>write</i> <code>b</code><code><img src="chars/arrwrite.gif"></code><i>read</i> <code>b</code> (then <code>ha=1</code>, <code>hb=1</code>, <code>ma=1</code>, <code>mb=1</code>, <code>ya=1</code>, <code>yb=1</code>)
</ul><a name="23973"></a>
While the resulting state is timing-dependent, it can be seen that the two threads 
will necessarily agree on the values of <code>a</code> and <code>b</code>.
<p><a name="23974"></a>
<hr><h2>8.11	 Example: Out-of-Order Writes</h2>
<a name="23975"></a>
This example is similar to that in the preceding section, except that one method 
assigns to both variables and the other method reads both variables. Consider a 
class that has class variables <code>a</code> and <code>b</code> and methods <code>to</code> and <code>fro</code>:
<p><pre><br><a name="23976"></a>&nbsp;&nbsp;&nbsp;&nbsp;class Simple {
</pre><pre>&nbsp;&nbsp;&nbsp;&nbsp;	int a = 1, b = 2;
&nbsp;&nbsp;&nbsp;&nbsp;	void to() {
&nbsp;&nbsp;&nbsp;&nbsp;		a = 3;
&nbsp;&nbsp;&nbsp;&nbsp;		b = 4;
&nbsp;&nbsp;&nbsp;&nbsp;	}
&nbsp;&nbsp;&nbsp;&nbsp;	void fro() 
&nbsp;&nbsp;&nbsp;&nbsp;		System.out.println("a= " + a + ", b=" + b);
&nbsp;&nbsp;&nbsp;&nbsp;	}
<a name="23985"></a>&nbsp;&nbsp;&nbsp;&nbsp;}
<br></pre><a name="23986"></a>
Now suppose that two threads are created, and that one thread calls <code>to</code> while the 
other thread calls <code>fro</code>. What is the required set of actions and what are the ordering constraints?
<p><a name="23987"></a>
Let us consider the thread that calls <code>to</code>. According to the rules, this thread must perform an <i>assign</i> of <code>a</code> followed by an <i>assign</i> of <code>b</code>. That is the bare minimum required to execute a call to the method <code>to</code>. Because there is no synchronization, it is at the option of the implementation whether or not to <i>store</i> the assigned values back to main memory! Therefore, the thread that calls <code>fro</code> may obtain either <code>1</code> or <code>3</code> for the value of <code>a</code>, and independently may obtain either <code>2</code> or <code>4</code> for the value of <code>b</code>.<p>
<a name="23988"></a>
Now suppose that <code>to</code> is <code>synchronized</code> but <code>fro</code> is not:<p>
<pre><br><a name="23989"></a>&nbsp;&nbsp;&nbsp;&nbsp;class SynchSimple {
</pre><pre>&nbsp;&nbsp;&nbsp;&nbsp;	int a = 1, b = 2;
&nbsp;&nbsp;&nbsp;&nbsp;	synchronized void to() {
&nbsp;&nbsp;&nbsp;&nbsp;		a = 3;
&nbsp;&nbsp;&nbsp;&nbsp;		b = 4;
&nbsp;&nbsp;&nbsp;&nbsp;	}
&nbsp;&nbsp;&nbsp;&nbsp;	void fro() 
&nbsp;&nbsp;&nbsp;&nbsp;		System.out.println("a= " + a + ", b=" + b);
&nbsp;&nbsp;&nbsp;&nbsp;	}
<a name="23998"></a>&nbsp;&nbsp;&nbsp;&nbsp;}
<br></pre><a name="23999"></a>
In this case the method <code>to</code> will be forced to <i>store</i> the assigned values back to main 
memory before the <i>unlock</i> operation at the end of the method. The method <code>fro</code> 
must, of course, use <code>a</code> and <code>b</code> (in that order) and so must <i>load</i> values for <code>a</code> and <code>b</code> 
from main memory.
<p><a name="24042"></a>
The total set of operations may be pictured as follows:<br><br><img src="Threads.doc.anc2.gif">
<br><br><p>
<a name="24043"></a>
Here an arrow from action A to action B indicates that A must precede B.
<p><a name="24044"></a>
In what order may the operations by the main memory occur? Note that the rules do not require that <i>write</i> <code>a</code> occur before <i>write</i> <code>b</code>; neither do they require that <i>read</i> <code>a</code> occur before <i>read</i> <code>b</code>. Also, even though method <code>to</code> is synchronized, method <code>fro</code> is not synchronized, so there is nothing to prevent the <i>read</i> operations from occurring between the <i>lock</i> and <i>unlock</i> operations. (The point is that declaring one method <code>synchronized</code> does not of itself make that method behave as if it were atomic.)<p>
<a name="24045"></a>
As a result, the method <code>fro</code> could still obtain either <code>1</code> or <code>3</code> for the value of <code>a</code>, and independently could obtain either <code>2</code> or <code>4</code> for the value of <code>b</code>. In particular, <code>fro</code> might observe the value <code>1</code> for <code>a</code> and <code>4</code> for <code>b</code>. Thus, even though <code>to</code> does an <i>assign</i> to <code>a</code> and then an <i>assign</i> to <code>b</code>, the <i>write</i> operations to main memory may be observed by another thread to occur as if in the opposite order. <p>
<a name="24046"></a>
Finally, suppose that <code>to</code> and <code>fro</code> are both <code>synchronized</code>:<p>
<pre><br><a name="24047"></a>&nbsp;&nbsp;&nbsp;&nbsp;class SynchSynchSimple {
</pre><pre>&nbsp;&nbsp;&nbsp;&nbsp;	int a = 1, b = 2;
&nbsp;&nbsp;&nbsp;&nbsp;	synchronized void to() {
&nbsp;&nbsp;&nbsp;&nbsp;		a = 3;
&nbsp;&nbsp;&nbsp;&nbsp;		b = 4;
&nbsp;&nbsp;&nbsp;&nbsp;	}
&nbsp;&nbsp;&nbsp;&nbsp;	synchronized void fro() 
&nbsp;&nbsp;&nbsp;&nbsp;		System.out.println("a= " + a + ", b=" + b);
&nbsp;&nbsp;&nbsp;&nbsp;	}
<a name="24056"></a>&nbsp;&nbsp;&nbsp;&nbsp;}
<br></pre><a name="24057"></a>
In this case, the actions of method <code>fro</code> cannot be interleaved with the actions of method <code>to</code>, and so <code>fro</code> will print either "<code>a=1, b=2</code>" or "<code>a=3, b=4</code>".<p>
<a name="22488"></a>
<hr><h2>8.12	 Threads</h2>
<a name="22492"></a>
Threads are created and managed by the classes <code>Thread</code> and <code>ThreadGroup</code>. Creating a <code>Thread</code> object creates a thread, and that is the only way to create a thread. 
When the thread is created, it is not yet active; it begins to run when its <code>start</code> 
method is called.
<p><a name="22500"></a>
<hr><h2>8.13	 Locks and Synchronization</h2>
<a name="22501"></a>
There is a lock associated with every object. The Java language does not provide a 
way to perform separate <i>lock</i> and <i>unlock</i> operations; instead, they are implicitly 
performed by high-level constructs that arrange always to pair such operations 
correctly. (The Java Virtual Machine, however, provides separate <i>monitorenter</i> 
and <i>monitorexit</i> instructions that implement the <i>lock</i> and <i>unlock</i> operations.)
<p><a name="24410"></a>
The <code>synchronized</code> statement computes a reference to an object; it then attempts to perform a <i>lock</i> operation on that object and does not proceed further until the <i>lock</i> operation has successfully completed. (A <i>lock</i> operation may be delayed because the rules about locks can prevent the main memory from participating until some other thread is ready to perform one or more <i>unlock</i> operations.) After the lock operation has been performed, the body of the <code>synchronized</code> statement is executed. If execution of the body is ever completed, either normally or abruptly, an <i>unlock</i> operation is automatically performed on that same lock.<p>
<a name="22509"></a>
A <code>synchronized</code> method automatically performs a <i>lock</i> operation when it is invoked; its body is not executed until the <i>lock</i> operation has successfully completed. If the method is an instance method, it locks the lock associated with the instance for which it was invoked (that is, the object that will be known as <code>this</code> during execution of the body of the method). If the method is <code>static</code>, it locks the lock associated with the <code>Class</code> object that represents the class in which the method is defined. If execution of the method's body is ever completed, either normally or abruptly, an <i>unlock</i> operation is automatically performed on that same lock.<p>
<a name="22510"></a>
Best practice is that if a variable is ever to be assigned by one thread and used or assigned by another, then all accesses to that variable should be enclosed in <code>synchronized</code> methods or <code>synchronized</code> statements.<p>
<a name="23513"></a>
<hr><h2>8.14	 Wait Sets and Notification</h2>
<a name="23518"></a>
Every object, in addition to having an associated lock, has an associated wait set, 
which is a set of threads. When an object is first created, its wait set is empty.
<p><a name="23519"></a>
Wait sets are used by the methods <code>wait</code>, <code>notify</code>, and <code>notifyAll</code> of class <code>Object</code>. These methods also interact with the scheduling mechanism for threads.<p>
<a name="23520"></a>
The method <code>wait</code> should be invoked for an object only when the current thread (call it T) has already locked the object's lock. Suppose that thread T has in fact performed N <i>lock</i> operations that have not been matched by <i>unlock</i> operations. The <code>wait</code> method then adds the current thread to the wait set for the object, disables the current thread for thread scheduling purposes, and performs N <i>unlock</i> operations to relinquish the lock. The thread T then lies dormant until one of three things happens:<p>
<ul><a name="23521"></a>
<li>Some other thread invokes the <code>notify</code> method for that object, and thread T happens to be the one arbitrarily chosen as the one to notify.
<a name="23525"></a>
<li>Some other thread invokes the <code>notifyAll</code> method for that object.
<a name="23526"></a>
<li>If the call by thread T to the <code>wait</code> method specified a time-out interval, then the specified amount of real time has elapsed.
</ul><a name="23527"></a>
The thread T is then removed from the wait set and re-enabled for thread scheduling. It then locks the object again (which may involve competing in the usual manner with other threads); once it has gained control of the lock, it performs N - 1 additional <i>lock</i> operations and then returns from the invocation of the <code>wait</code> method. Thus, on return from the <code>wait</code> method, the state of the object's lock is exactly as it was when the <code>wait</code> method was invoked.<p>
<a name="23528"></a>
The <code>notify</code> method should be invoked for an object only when the current thread has already locked the object's lock, or an <code>IllegalMonitorState</code>-<code>Exception</code> will be thrown. If the wait set for the object is not empty, then some arbitrarily chosen thread is removed from the wait set and re-enabled for thread scheduling. (Of course, that thread will not be able to proceed until the current thread relinquishes the object's lock.)<p>
<a name="23537"></a>
The <code>notifyAll</code> method should be invoked for an object only when the current thread has already locked the object's lock, or an <code>IllegalMonitorState</code><code>Exception</code> will be thrown. Every thread in the wait set for the object is removed from the wait set and re-enabled for thread scheduling. (Of course, those threads will not be able to proceed until the current thread relinquishes the object's lock.)<p>
<a name="23512"></a>
<p>


<hr>
<!-- This inserts footnotes--><p>
<br>
<a href="VMSpecTOC.doc.html">Contents</a> | <a href="Compiling.doc.html">Prev</a> | <a href="Quick.doc.html">Next</a> | <a href="Lindholm.INDEX.html">Index</a>
<p>
<font size = -1>Java Virtual Machine Specification <br>
<!--(HTML generated by dkramer on March 31, 1997)-->
<!--
(HTML generated by dkramer on March 25, 1997)-->
<br>
<i><a href="Copyright.doc.html">Copyright &#169 1996, 1997 Sun Microsystems, Inc.</a>
All rights reserved</i>
<br>
Please send any comments or corrections to <a href="mailto:jvm@java.sun.com">jvm@java.sun.com</a>
</font>
</body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -