JAVA shared locks and conditional variables twos __java

Source: Internet
Author: User
Tags instance method int size semaphore thread class

There is a need for coordination between multithreading. For example, a browser's thread that displays a picture Displaythread wants to perform the task of displaying a picture, and must wait for the download thread downloadthread to download the picture. If the picture has not been downloaded, displaythread can pause, when Downloadthread completed the task, and then notify Displaythread "picture ready, you can show", then Displaythread continue to execute.

The above logic is simply: if the condition is not satisfied, then wait. When the condition is satisfied, the thread that waits for the condition is awakened. In Java, the implementation of this mechanism relies on wait/notify. The wait mechanism is closely related to the lock mechanism. For example:

Synchronized (obj) {
while (!condition) {
Obj.wait ();
}
Obj.dosomething ();
}

When thread a obtains the obj lock, the discovery condition condition is not satisfied and cannot proceed to the next processing, so thread A is wait ().

In another thread B, if B changes certain conditions so that thread A's condition condition is satisfied, thread A can be awakened:

Synchronized (obj) {
Condition = true;
Obj.notify ();
}

The concepts that need to be noted are:

# to call obj's Wait (), the Notify () method must obtain the obj lock, which means that it must be written in the synchronized (obj) {...} code snippet.

# after calling obj.wait (), thread a releases the lock on obj, otherwise thread B cannot get the obj lock and cannot wake a in the synchronized (obj) {...} code snippet.

# when the Obj.wait () method returns, thread a needs to acquire the obj lock again before execution can continue.

# If a1,a2,a3 are all in obj.wait (), then B calls Obj.notify () can only wake one of the A1,A2,A3 (which is determined by the JVM).

# Obj.notifyall () can awaken all a1,a2,a3, but to continue executing the next Statement of Obj.wait (), the obj lock must be obtained, so A1,A2,A3 has only one chance to get the lock to continue execution, such as A1, The rest needs to wait for A1 to release the obj lock before proceeding.

# when B calls Obj.notify/notifyall, B is holding the obj lock, so a1,a2,a3 is awakened, but still unable to get the obj lock. Until B exits the synchronized block and releases the obj lock, one of the A1,A2,A3 has the opportunity to obtain the lock to continue execution.

4 Ways to use synchronized

1. Method declaration, after a range operator (public, and so on), before returning a type declaration (void, etc.). That is, only one thread at a time can enter the method, and other threads will have to wait in line to call the method at this time, the current thread (that is, the thread inside the synchronized After the method has been executed, other threads can enter.

For example:

Public synchronized void Synmethod () {
Method body
}

2. Used for a block of code, synchronized followed by parentheses, and a variable in parentheses, so that only one thread at a time enters the code block. For example:

public int Synmethod (int A1) {
Synchronized (A1) {
Only one thread can enter at a time
}
}
3.synchronized the back bracket is an object, at which point the thread obtains an object lock. For example:

public class Mythread implements Runnable {
public static void Main (String args[]) {
mythread MT = new Mythread ();
thread T1 = new Thread (MT, T1);
Thread t2 = new Thread (MT, T2);
thread t3 = new Thread (MT, T3);
thread T4 = new Thread (MT, T4);
Thread T5 = new Thread (MT, T5);
Thread T6 = new Thread (MT, T6);
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
T6.start ();
}

public void Run () {
Synchronized (this) {
System.out.println (Thread.CurrentThread (). GetName ());
}
}
}

For 3, if the thread enters, the object lock is obtained, and no other thread can do anything on all of the objects in the class. Using locks at the object level is usually a rough method. Why do you lock the entire object, instead of allowing other threads to temporarily use other synchronization methods in the object to access the shared resource? If an object has more than one resource, it does not need to lock all threads out just to allow one thread to use one of the resources. Because each object has a lock, you can use the virtual object to lock as follows:

Class Finegrainlock {

Mymemberclass x, y;
Object Xlock = new Object (), Ylock = new Object ();

public void Foo () {
Synchronized (Xlock) {
Access x here
}

Do something here-but don ' t with shared resources

Synchronized (Ylock) {
Access Y here
}
}

public void Bar () {
Synchronized (this) {
Access both X and Y
}
Do something here-but don ' t with shared resources
}
}

4.synchronized back brackets are classes. For example:

Class arraywithlockorder{
private static Long num_locks = 0;
Private long Lock_order;
Private int[] arr;

Public Arraywithlockorder (int[] a)
{
arr = A;
Synchronized (Arraywithlockorder.class) {//-----------------------------------------here
num_locks++; Lock number plus 1.
Lock_order = Num_locks; Sets the unique lock_order for this object instance.
}
}
Public long Lockorder ()
{
return lock_order;
}
Public int[] Array ()
{
return arr;
}
}

Class SomeClass implements Runnable
{
public int Sumarrays (Arraywithlockorder A1,
Arraywithlockorder A2)
{
int value = 0;
Arraywithlockorder-A1; Preserves an array reference to a
Arraywithlockorder last = A2; Local copy.
int size = A1.array (). length;
if (size = = A2.array (). Length)
{
if (A1.lockorder () > A2.lockorder ())//Determine and set lock on object
{//order.
i = A2;
last = A1;
}
Synchronized (a) {//Lock objects in the correct order.
Synchronized (last) {
int[] arr1 = A1.array ();
int[] arr2 = A2.array ();
for (int i=0 I value + = Arr1[i] + arr2[i];
}
}
}
return value;
}
public void Run () {
//...
}
}

For 4, if a thread enters, the thread cannot do all the operations in the class, including static variables and static methods, and in fact, we usually use 4来 for synchronization of code blocks that contain static methods and static variables.

The relationship between the above 4 species:

A lock is associated with an object, and each object has a lock, in order to execute the synchronized statement, the thread must be able to obtain the lock of the object specified in the expression in the synchronized statement, an object that has only one lock, and it no longer owns the lock after being acquired by a thread, When the thread finishes executing the SYNCHRONIZED statement, it returns the lock to the object.
You can declare a method as a synchronized method by preceding the method with the synchronized modifier. The synchronization method obtains a lock before executing. If this is a class method, the lock obtained is the lock of the class object associated with the class that declares the method. If this is an instance method, then this lock is a lock on the This object.


Here are some common approaches:

Waits (), wait (Long), notify (), Notifyall () are instance methods of the current class.

Wait () is the thread that holds the object lock to release the lock;
Wait (long) is a lock that holds an object lock, after the thread releasing the lock time is long (milliseconds), the second is the same, and wait () and wait (0) are equivalent;
Notify () is a thread that wakes up a lock waiting for the object, and if more than one thread is waiting, the awakened thread is determined by the JVM;
Notifyall is a thread that wakes up all the locks that are waiting for the object.
Here I also reiterate that we should give priority to using the Notifyall () method, since it is easier to wake up all threads than to wake up a thread to let the JVM find the thread that best fits the wake.

For the above method, it can only be used in the critical resources of the current thread, otherwise the report run-time error java.lang.IllegalMonitorStateException:current thread not owner.

Next, I'll talk about the relationship between synchronized and wait (), notify ():

1. Where there is synchronized, there is not necessarily wait,notify

2. Where there are wait,notify, there must be synchronized. This is because wait and notify are not part of the thread class, but the methods each object has, and both of these methods are related to the object lock, where there is a lock, there must be a synchronized.

Also, be aware that if you want to put the notify and the wait method together, you must call wait after calling notify, because if you call, the thread is already not current thread. The following example:

/**
* title:jdeveloper ' s Java projdect
* DESCRIPTION:N/A
* Copyright:copyright (c) 2001
* Company:soho http://www.ChinaJavaWorld.com
* @author jdeveloper@21cn.com
* @version 1.0
*/
Import java.lang.Runnable;
Import Java.lang.Thread;

public class DemoThread
Implements Runnable {

Public DemoThread () {
Testthread testthread1 = new Testthread (this, 1);
Testthread testthread2 = new Testthread (this, 2);

Testthread2.start ();
Testthread1.start ();

}

public static void Main (string[] args) {
DemoThread demoThread1 = new DemoThread ();

}

public void Run () {

Testthread t = (testthread) thread.currentthread ();
try {
if (!t.getname (). Equalsignorecase (1)) {
Synchronized (this) {
Wait ();
}
}
while (true) {

SYSTEM.OUT.PRINTLN (@time in Thread + t.getname () + = +
T.increasetime ());

if (t.gettime ()% 10 = 0) {
Synchronized (this) {
System.out.println (****************************************);
Notify ();
if (t.gettime () = = 100)
Break
Wait ();
}
}
}
}
catch (Exception e) {
E.printstacktrace ();
}
}

}

Class Testthread
Extends Thread {
private int time = 0;
Public Testthread (Runnable R, String name) {
Super (R, name);
}

public int GetTime () {
return time;
}

public int Increasetime () {
Return++time;
}

}

Here we use the producer/consumer example to illustrate the relationship between them:

public class Test {
public static void Main (String args[]) {
Semaphore s = new semaphore (1);
thread T1 = new Thread (s, producer1);
Thread t2 = new Thread (s, producer2);
thread t3 = new Thread (s, Producer3);
thread T4 = new Thread (s, consumer1);
Thread T5 = new Thread (s, consumer2);
Thread T6 = new Thread (s, Consumer3);
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
T6.start ();
}
}

Class semaphore
Implements Runnable {
private int count;
public semaphore (int n) {
This.count = n;
}

public synchronized void Acquire () {
while (count = = 0) {
try {
Wait ();
}
catch (Interruptedexception e) {
Keep trying
}
}
count--;
}

Public synchronized void release () {
while (count = = 10) {
try {
Wait ();
}
catch (Interruptedexception e) {
Keep trying
}
}
count++;
Notifyall (); Alert a thread that "s blocking on this semaphore
}

public void Run () {
while (true) {
if (Thread.CurrentThread (). GetName (). substring (0,8). Equalsignorecase (consumer)) {
Acquire ();
}
else if (Thread.CurrentThread (). GetName (). substring (0,8). Equalsignorecase (producer)) {
Release ();
}
System.out.println (Thread.CurrentThread (). GetName () + + count);
}
}
}

Producer production, consumer consumption, there is generally no conflict, but when the inventory of 0 o'clock, consumers will not be able to consume, but when the inventory is capped (here is 10), the producers can not produce. Please read the above procedure carefully, you will certainly make much progress than before.

The code above illustrates that there is no absolute relationship between synchronized and wait,notify, and that you can do without wait,notify in the method, block of code that synchronized declares, but if the thread has some contention for a resource, You have to put the thread into the waiting or awakening in due course.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.