(next to Thread base: Thread (2) basic threading operation in--java (above) ")
1-4, pay attention to the use of synchronized keywords
In the previous article, we mainly explain how the "object lock" works in threads and how to do it. When explaining the Synchronized keyword, we also mentioned the location where the Synchronized keyword can be labeled. You often see quite a few web stickers, loading the synchronized keyword into the code's method body in their code example, and then telling the reader that this operation is thread-safe. The code might look like this:
/** * 这个类的class对象进行检查。 */publicstaticsynchronizedvoiddoSomething() {}/** * 对这个类的实例化对象进行检查 */publicsynchronizedvoiddoOtherthing() {}
But in fact, whether an object is thread-safe is more important than adding the Synchronized keyword to see how this object is manipulated . In the code below, we show the Dootherthing method in two threads (so-called thread-safe method) to manipulate an object nowvalue:
PackageTest.thread.yield;ImportOrg.apache.commons.logging.Log;ImportOrg.apache.commons.logging.LogFactory;ImportOrg.apache.log4j.BasicConfigurator;/** * Used to wait for wake-up after startup * @author Yinwenjie * * Public class syncthread implements Runnable { /** * Log * * Private Static FinalLog LOGGER = Logfactory.getlog (Syncthread.class);PrivateInteger value;Private StaticInteger Nowvalue;Static{basicconfigurator.configure (); } Public Syncthread(intValue) { This. value = value; }/** * Check the instantiation object of this class * / Private synchronized void dootherthing() {Nowvalue = This. value; Logger.info ("The value of the current Nowvalue:"+ Nowvalue); }@Override Public void Run() {Thread CurrentThread = Thread.CurrentThread (); Long id = currentthread.getid (); This. dootherthing (); } Public Static void Main(string[] args)throwsException {Thread SyncThread1 =NewThread (NewSyncthread (Ten)); Thread syncThread2 =NewThread (NewSyncthread ( -)); Syncthread1.start (); Syncthread2.start (); }}
In the case of debug, there may be a dirty read of the value of the static object Nowvalue:
0 [Thread-1] INFO test.thread.yield.SyncThread - 当前NOWVALUE的值:100730 [Thread-0] INFO test.thread.yield.SyncThread - 当前NOWVALUE的值:100
Here's why the code has a bug:
The SyncThread1 object and the SyncThread2 object are two different instances of the Syncthread class. The Synchronized keyword in the private synchronized void dootherthing () method actually makes a different target for the synchronization check.
If you want to perform a synchronous check of multiple instance objects of a class, you should check the class object for the classes synchronously. The wording should be: "Private synchronized static void Dootherthing ()"
Of course, in order to check the class object of this kind (syncthread), you don't even have to label the synchronized keyword on a static method, and the object lock state check of Syncthread class is individually labeled:
privatevoiddoOtherthing() { synchronized (SyncThread.class) { this.value; LOGGER.info("当前NOWVALUE的值:" + NOWVALUE); }}
Therefore, whether an object is thread-safe in addition to adding synchronized keyword, but also to see how to do the operation of this object, the method labeled synchronized keyword, the operation for an object is not necessarily thread-safe!
2. Basic threading Operations in Java
This is the thread state switch legend that has been given in the previous article, and perhaps some readers do not fully understand the switching conditions, but it's okay to start with this section we'll go into more detail about how these thread states work in Java.
This section explains notify, Notifyall, interrupt, join, and sleep, in addition to the wait, wait (time) operations that were mentioned in the previous section when explaining "object locks."
2-1, notify and Notifyall operation
In the Java JDK, the explanations for the Notify method and the Notifyall method are:
Wakes up a single thread, that's waiting on this object ' s monitor. If any threads was waiting on the This object, one of the them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object ' s monitor by calling one of the wait methods.
The awakened thread is not being able to proceed until the current thread relinquishes the lock on this object. The awakened thread would compete in the usual manner with any other threads that might being actively competing to Synchroniz E on the This object; For example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object .
Wakes up all threads is waiting on this object ' s monitor. A thread waits on an object ' s monitor by calling one of the wait methods.
The awakened threads is not being able to proceed until the current thread relinquishes the lock on this object. The awakened threads would compete in the usual manner with any other threads that might being actively competing to Synchroni Ze on this object; For example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object .
To illustrate the work of the Notify method and the Notifyall method, I will give a piece of code for these two methods and explain them in detail.
The work of 2-1-1 and notify methods
- Parentnotifythread class:
Packagetest.thread.notify;ImportOrg.apache.log4j.BasicConfigurator;/** * This thread is used to make notify requests * @author Yinwenjie */ Public class parentnotifythread implements Runnable { /** * The "key" of this object, held for each Childnotifythread object, simulates this object as an exclusive phenomenon for all Childnotifythread objects */ Public Static FinalObject Wait_chileobject =NewObject ();Static{basicconfigurator.configure (); } Public Static void Main(string[] args)throwsException {NewThread (NewParentnotifythread ()). Start (); } Public void Run() {/ * * 3 threads for independent preemption of Wait_chileobject objects, observation * */ intMaxindex =3; for(intindex =0; Index < Maxindex; index++) {Childnotifythread childnotify =NewChildnotifythread (); Thread Childnotifythread =NewThread (childnotify); Childnotifythread.start (); }/* * Please add eclipse breakpoints here, * to ensure that the wait () method in Childnotifythread is first executed. * * in real-world situations, you can block by a Boolean (or otherwise) * You can also use the Countdownlatch class * */ synchronized(Parentnotifythread.wait_chileobject) {ParentNotifyThread.WAIT_CHILEOBJECT.notify (); }//no specific presentation meaning; //Just to make sure Parentnotifythread won't quit synchronized(Parentnotifythread.class) {Try{ParentNotifyThread.class.wait (); }Catch(Interruptedexception e) {E.printstacktrace (); } } }}
Packagetest.thread.notify;ImportOrg.apache.commons.logging.Log;ImportOrg.apache.commons.logging.LogFactory;/** * Used to wait for wake-up after startup * @author Yinwenjie * * Public class childnotifythread implements Runnable { /** * Log * * Private Static FinalLog LOGGER = Logfactory.getlog (Childnotifythread.class);@Override Public void Run() {Thread CurrentThread = Thread.CurrentThread ();Longid = Currentthread.getid (); ChildNotifyThread.LOGGER.info ("Threads"+ ID +"Start successfully, ready to enter the waiting state");synchronized(Parentnotifythread.wait_chileobject) {Try{ParentNotifyThread.WAIT_CHILEOBJECT.wait (); }Catch(Interruptedexception e) {ChildNotifyThread.LOGGER.error (E.getmessage (), E); } }//Execute here to indicate that the thread has been awakenedChildNotifyThread.LOGGER.info ("Threads"+ ID +"Be awakened!" "); }}
In the above two pieces of code, the Parentnotifythread class is responsible for creating objects of three childnotifythread classes, each of which has an instance object of Childnotifythread class holding Parentnotifythread.wait_ Chileobject the "key" of the object and exits the exclusive state of the Parentnotifythread.wait_chileobject object through the WAIT method (but does not return the lock), as shown in:
We then unblocked the blocking state through the ParentNotifyThread.WAIT_CHILEOBJECT.notify () method in the Parentnotifythread class:
synchronized (ParentNotifyThread.WAIT_CHILEOBJECT) { ParentNotifyThread.WAIT_CHILEOBJECT.notify();}
The above code performs as follows:
0[thread-1] INFO Test. Thread. Notify. Childnotifythread-Thread -Start successfully, ready to enter the waiting state1[thread-2] INFO Test. Thread. Notify. Childnotifythread-Thread theStart successfully, ready to enter the waiting state1[thread-3] INFO Test. Thread. Notify. Childnotifythread-Thread -Start successfully, ready to enter the waiting state87285[thread-1] INFO Test. Thread. Notify. Childnotifythread-Thread -Be awakened!
In fact, we only know that there are three instance objects of the Childnotifythread class that are waiting for the Parentnotifythread.wait_chileobject object's "lock core" idle We do not know that the ParentNotifyThread.WAIT_CHILEOBJECT.notify () method will "lock the core" of the Parentnotifythread.wait_chileobject object (exclusive) to which thread of the three threads (this decision process is done by the operating system). and we also know that the ParentNotifyThread.WAIT_CHILEOBJECT.notify () method will only wake up waiting for Parentnotifythread.wait_chileobject object "lock Core" One of the three instance objects of the Childnotifythread class (exclusive rights) .
The work of 2-1-2 and Notifyall methods
Actually understanding the work of the Notify () method, it is not difficult to understand the work of the Notifyall () method. Next, the same code as the above section, we will parentnotifythread the ParentNotifyThread.WAIT_CHILEOBJECT.notify () method in the class, Replace with the ParentNotifyThread.WAIT_CHILEOBJECT.notifyAll () method. As shown in the following code snippet:
synchronized (ParentNotifyThread.WAIT_CHILEOBJECT) { ParentNotifyThread.WAIT_CHILEOBJECT.notifyAll();}
Then we observe the result of the code execution:
0[thread-2] INFO Test. Thread. Notify. Childnotifythread-Thread theStart successfully, ready to enter the waiting state0[thread-1] INFO Test. Thread. Notify. Childnotifythread-Thread -Start successfully, ready to enter the waiting state0[thread-3] INFO Test. Thread. Notify. Childnotifythread-Thread -Start successfully, ready to enter the waiting state26834[thread-3] INFO Test. Thread. Notify. Childnotifythread-Thread -Be awakened!30108[thread-1] INFO Test. Thread. Notify. Childnotifythread-Thread -Be awakened!35368[thread-2] INFO Test. Thread. Notify. Childnotifythread-Thread theBe awakened!
We see the fact that three threads in the system that are waiting for the "lock Core" (exclusive) of the Arentnotifythread.wait_chileobject object lock are woken up sequentially (with exclusive rights in turn).
(next)
Thread Base: Thread (3) basic threading operations in--java (middle)