📄 17.doc.html
字号:
<a name="29321"></a> a = 3;
<a name="29322"></a> b = 4;
<a name="29323"></a> }
<a name="29324"></a> void fro() {
<a name="29325"></a> System.out.println("a= " + a + ", b=" + b);
<a name="29326"></a> }
<a name="29327"></a>}
</pre><a name="29316"></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> action 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="29336"></a>
The total set of actions may be pictured as follows:<img src="17.doc.anc2.gif"><p>
<a name="29234"></a>
Here an arrow from action <i>A</i> to action <i>B</i> indicates that <i>A</i> must precede <i>B</i>.
<p><a name="29235"></a>
In what order may the actions 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 <code>synchronized</code>, method <code>fro</code> is not <code>synchronized</code>, so there is nothing to prevent the <i>read</i> actions from occurring between the <i>lock</i> and <i>unlock</i> actions. (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="29398"></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> actions to main memory may be observed by another thread to occur as if in the opposite order.<p>
<a name="45366"></a>
<p>
<a name="45367"></a>
<p>
<a name="45368"></a>
<p>
<a name="45369"></a>
<p>
<a name="45669"></a>
<p>
<a name="45370"></a>
<p>
<a name="29431"></a>
Finally, suppose that <code>to</code> and <code>fro</code> are both <code>synchronized</code>:<p>
<pre><a name="29432"></a>
class SynchSynchSimple {
<a name="29433"></a> int a = 1, b = 2;
<a name="29434"></a> synchronized void to() {
<a name="29435"></a> a = 3;
<a name="29436"></a> b = 4;
<a name="29437"></a> }
<a name="29438"></a> synchronized void fro() {
<a name="29439"></a> System.out.println("a= " + a + ", b=" + b);
<a name="29440"></a> }
<a name="29441"></a>}
</pre><a name="29386"></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="28457"></a>
<h2>17.12 Threads</h2>
<a name="28458"></a>
Threads are created and managed by the built-in classes <code>Thread</code> <a href="javalang.doc18.html#2658">(§20.20)</a> and
<code>ThreadGroup</code> <a href="javalang.doc19.html#14469">(§20.21)</a>. 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 <a href="javalang.doc18.html#8093">(§20.20.14)</a> is called.
<p><a name="44439"></a>
Every thread has a <i>priority</i>. When there is competition for processing resources, threads with higher priority are generally executed in preference to threads with lower priority. Such preference is not, however, a guarantee that the highest priority thread will always be running, and thread priorities cannot be used to reliably implement mutual exclusion.<p>
<a name="28460"></a>
<h2>17.13 Locks and Synchronization</h2>
<a name="28461"></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> actions; instead, they are implicitly performed
by high-level constructs that arrange always to pair such actions correctly.
(We note, however, that the Java Virtual Machine provides separate <i>monitorenter</i>
and <i>monitorexit</i> instructions that implement the <i>lock</i> and <i>unlock</i> actions.)
<p><a name="28465"></a>
The <code>synchronized</code> statement <a href="14.doc.html#79287">(§14.17)</a> computes a reference to an object; it then attempts to perform a <i>lock</i> action on that object and does not proceed further until the <i>lock</i> action has successfully completed. (A <i>lock</i> action 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> actions.) After the lock action 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> action is automatically performed on that same lock.<p>
<a name="28469"></a>
A <code>synchronized</code> method <a href="8.doc.html#55408">(§8.4.3.5)</a> automatically performs a <i>lock</i> action when it is invoked; its body is not executed until the <i>lock</i> action 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> action is automatically performed on that same lock.<p>
<a name="28470"></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="45472"></a>
Java does not prevent, nor require detection of, deadlock conditions. Programs where threads hold (directly or indirectly) locks on multiple objects should use conventional techniques for deadlock avoidance, creating higher-level locking primitives that don't deadlock, if necessary.<p>
<a name="28471"></a>
<h2>17.14 Wait Sets and Notification</h2>
<a name="29596"></a>
Every object, in addition to having an associated lock, has an associated <i>wait set</i>,
which is a set of threads. When an object is first created, its wait set is empty.
<p><a name="29597"></a>
Wait sets are used by the methods <code>wait</code> (<a href="javalang.doc1.html#33394">§20.1.6</a>, <a href="javalang.doc1.html#14926">§20.1.7</a>, <a href="javalang.doc1.html#32520">§20.1.8</a>), <code>notify</code> <a href="javalang.doc1.html#13789">(§20.1.9)</a>, and <code>notifyAll</code> <a href="javalang.doc1.html#13790">(§20.1.10)</a> of class <code>Object</code>. These methods also interact with the scheduling mechanism for threads <a href="javalang.doc18.html#2658">(§20.20)</a>.<p>
<a name="29731"></a>
The method <code>wait</code> should be called for an object only when the current thread (call it <i>T</i>) has already locked the object's lock. Suppose that thread <i>T</i> has in fact performed <i>N lock</i> actions that have not been matched by <i>unlock</i> actions. 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 <i>N</i> <i>unlock</i> actions to relinquish the lock. The thread <i>T</i> then lies dormant until one of three things happens:<p>
<ul><a name="29732"></a>
<li>Some other thread invokes the <code>notify</code> method for that object and thread <i>T</i> happens to be the one arbitrarily chosen as the one to notify.
<a name="29721"></a>
<li>Some other thread invokes the <code>notifyAll</code> method for that object.
<a name="29664"></a>
<li>If the call by thread <i>T</i> to the wait method specified a timeout interval, the specified amount of real time has elapsed.
</ul><a name="29669"></a>
The thread <i>T</i> 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
<img src="17.doc.anc3.gif"> additional <i>lock</i> actions 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="29772"></a>
The <code>notify</code> method should be called for an object only when the current thread has already locked the object's lock. 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="29776"></a>
The <code>notifyAll</code> method should be called for an object only when the current thread has already locked the object's lock. 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>
<hr>
<!-- This inserts footnotes--><p>
<a href="index.html">Contents</a> | <a href="16.doc.html">Prev</a> | <a href="18.doc.html">Next</a> | <a href="j.index.doc1.html">Index</a>
<p>
<font size=-1>Java Language Specification (HTML generated by Suzette Pelouch on February 24, 1998)<br>
<i><a href="jcopyright.doc.html">Copyright © 1996 Sun Microsystems, Inc.</a>
All rights reserved</i>
<br>
Please send any comments or corrections to <a href="mailto:doug.kramer@sun.com">doug.kramer@sun.com</a>
</font>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -