- Using synchronized to implement synchronization methods
- Using non-dependent properties for synchronization
- Use conditions in synchronization blocks (Wait (), notify (), Notifyall ())
- Using Locks for synchronization
- Use read-write locks for synchronous data access
- Change the fairness of a lock
- Using multiple conditions in locks (Multri Condition)
Body
One of the most common scenarios in concurrent programming is the scenario where multiple threads of execution share a resource. Data inconsistencies can occur when multiple threads read or write the same data. In order to solve these problems, the concept of critical region is introduced. A critical section is a block of code that accesses a shared resource, which allows only one thread to execute at the same time.
Java provides a synchronization mechanism. When a thread attempts to access a critical section, it uses a synchronization mechanism to see if another thread has entered the critical section. If no other thread enters the critical section, it can enter the critical section, and if it has entered the critical section, it is suspended by the synchronization mechanism until the incoming thread leaves the critical section. If more than one thread waits to enter the critical section, the JVM willrandomly select one of them and the rest will continue to wait. Good understanding of the concept, concrete in the Java program is how to embody it? What is the code for the critical section? Back to the top using synchronized to implement synchronization methods every method declared with the Synchronized keyword is a critical section. In Java,The critical section of the same object, at the same time only one allowed to be accessed. Note: Static methods declared with the Synchronized keyword can only be accessed by one thread of execution, but other threads have access to the non-static method of the object. That is: Two threads can access the two different synchronized methods of an object at the same time, one of which is a static method and one is a non-static method. Know the role of the Synchronized keyword, and then look at the use of the Synchronized keyword.
- Using the Synchronized keyword in a code block, obj can typically use the This keyword to represent this class of objects
1 synchronized (obj) {2}
Note: As mentioned earlier, the introduction of the Synchronized keyword is to declare a critical section to address the security of data changes that share variables in a multithreaded environment. Then, the general use of the Synchronized keyword is where the shared data access or modification. Here is an example of an example scenario: The company will make a regular payment to the account, the bank to debit the account. So money is a shared data for banks and companies. Then the Synchronized keyword should be used where the account is modified. Declare an account class:
1 public class Account {2 private double balance, 3 public double GetBalance () {4 return balance; 5 } 6< c4/>public void Setbalance (double balance) {7 this.balance = balance; 8 } 9 public synchronized void Addamoun T (double amount) {Ten double tmp=balance;11 try { Thread.Sleep (Ten) } catch ( Interruptedexception e) { e.printstacktrace (); }16 tmp+=amount;17 balance=tmp;18 } Public synchronized void Subtractamount (double amount) {double tmp=balance;21 try { Thread.Sleep ( interruptedexception e) { e.printstacktrace (); }26 tmp-= amount;27 balance=tmp;28 }29}
Bank type of deduction:
1 public class Bank implements Runnable {2 private account, 3 public Bank (account account) {4 THIS.A Ccount=account; 5 } 6 public void Run () {7 for (int i=0; i<100; i++) {8 account.subtractamount (+); 9 }10 } 11}
Company Class Payment:
1 public class Company implements Runnable {2 private account, 3 public company {4
this.account=account; 5 } 6 7 public Void Run () {8 for (int i=0; i<100; i++) {9 Account.addamount ( +); }12}
It is important to note that the parameters passed in the bank and company's constructors are account, which is a shared data. Main function:
1 public class Main {2 publicly static void main (string[] args) {3 account account=new account (); 4 Accoun T.setbalance (1000); 5 company Company=new Company, 6 thread companythread=new thread (company); 7 Bank Bank=new Bank (account); 8 Thread bankthread=new thread (bank), 9 Companythread.start (), one Bankthread.start (), and try {13 Companythread.join (); bankthread.join (); System.out.printf ("account:final Balance:%f\n", Account.getbalance ()); interruptedexception catch (e) { e.printstacktrace (); }19 }20}
This is a simple example, but it can explain the problem. Add: 1. The synchronized keyword reduces the performance of your application, so you can only use it on methods that modify shared data in a concurrent scenario. 2. Access to the critical section should be as short as possible. The remainder of the method remains outside the synchronized code block for better performance back to the top using non-dependent properties to implement synchronous non-dependency properties: For example, there are two non-dependent properties in a class, Object obj1,object obj2; they are shared by multiple threads, At the same time, only one thread is allowed to access one of the property variables, and the otherOne thread accesses another property variable. Examples are as follows: Two movie-watching rooms and two ticket outlets, one ticket sold at a ticket office, only for one of the cinemas. Cannot act on two movie rooms at the same time. Cinema class:
1 public class Cinema {2 private long vacanciesCinema1; 3 private long vacanciesCinema2; 4 5 Private final Object controlCinema1, ControlCinema2; 6 7 public Cinema () {8 Controlcinema1=new object (); 9 Controlcinema2=new object (); Vacancie Scinema1=20;11 vacanciescinema2=20;12}13 public boolean sellTickets1 (int number) {Sync Hronized (CONTROLCINEMA1) {if (NUMBER<VACANCIESCINEMA1) {vacanciescinema1-=number;18 Return true;19} else {return false;21}22}23}24 public boolean sellTickets2 (int number) {synchronized (CONTROLCINEMA2) {if (number< ; vacanciesCinema2) {vacanciescinema2-=number;29 return true;30} else {31 return false;32}33}34}35-Public boolean ReturnTickets1 (int number) {PNs synchronized (CONTROLCINEMA1) {vacanciescinema1+=number;39 return true;40} }42 public boolean returnTickets2 (int number) {synchronized (CONTROLCINEMA2) {Vacanc iescinema2+=number;45 return true;46}47}48 public Long getVacanciesCinema1 () {RET Urn vacanciescinema1;50}51 public long GetVacanciesCinema2 () {return vacanciescinema2;53}54}In this case, VACANCIESCINEMA1 and Vacanciescinema2 (the remaining votes) are independent because they belong to different objects. In this case, only one thread is allowed to modify VACANCIESCINEMA1 or VACANCIESCINEMA2, but two threads are allowed to modify both VACANCIESCINEMA1 and vacanciescinema2 at the same time. Go back to the top using conditions in the synchronization block (Wait (), notify (), Notifyall ()) First need to be clear:
- The above three methods are all methods of the object class.
- All three of these methods must be used in a synchronous code block.
when a thread calls the Wait () method, the JVM put the thread into hibernation and frees the object that controls the synchronization code block while allowing other threads to execute other synchronized blocks of code that the object controls. In order to wake up this thread, the notify () or Notifyall () method must be called in one of the synchronized code blocks controlled by this object. The above passage is very important!!! It illustrates the use of the three functions described above and how the method works. Wait (): Put the thread into hibernation and release the object that controls the synchronization code block, freeing up additional blocks of code that other threads can then perform to control the object. Which means you can get in. Unlike the Thread.Sleep (millions) method, the Sleep () method is automatically awakened after a specified time in sleep. Notify ()/notifyall (): A thread sleeping with the Wait () method needs to invoke the Notify or Notifyall () method to wake up in a synchronized code block controlled by the object in order to enter a ready state to wait for a call from the JVM. Otherwise, the consistency is dormant. Difficulty: The time when thread sleeps and wakes up, is to say when to call notify () or Notifyall () method??? In the case of producers and consumers, the producer plugs data into the queue and the consumer takes the data from the queue, so this queue is the shared data data storage class Eventstorage plug data method and Fetch data method: Set (), Get ()
1 public synchronized void set () {2 while (Storage.size () ==maxsize) {3 try {4 wait (); 5 } catch (Interrup Tedexception e) {6 e.printstacktrace (), 7 } 8 } 9 Storage.add (New Date ()), and System.out.printf (" Set:%d\n ", Storage.size ()), one notify (), and a public synchronized void get () { Storage.size () ==0) { try {c } (); C } catch (Interruptedexception e) { e.printstacktrace ( ); }20 }21 System.out.printf ("Get:%d:%s\n", Storage.size (), ((linkedlist<?>) storage). Poll ()); notify ();
Analysis of the above simple program: 1, the method uses the SYNCHRONIZED keyword to declare the synchronization code block. So the synchronization condition can be used within this function. 2, first determine whether the queue is full, here to use while instead of if. Why is it? While is whether the consistent query is full, and if is judged once it's done. 3, if full, call the Wait () method to release the object, then other methods (such as get ()) can use this object. The Get () method enters and then pulls out a data and wakes up the last dormant thread. 4. Although the thread is awakened, the set () method is blocked because the get () method thread occupies the object lock. Until the Get () method takes out all the data to satisfy the sleep condition, the Set () method re-executes 5, repeating the above steps back to the top using a lock to implement synchronous Java provides another mechanism for synchronizing code blocks, which is more powerful and more flexible than the synchronized keyword. This mechanism is based on the lock interface and its implementation class (for example: Reentrantlock) where it is better than the Synchronized keyword: 1, providing more functionality. The implementation of the Trylock () method, which attempts to acquire a lock, returns false and continues execution of the code if the lock is already occupied by another thread. 2. The lock interface allows separate read and write operations, allowing multiple threads to read and only one write thread. ReentrantReadWriteLock3, with better performance a lock's use instance:
1 public class PrintQueue {2 private final Lock queuelock=new Reentrantlock (); 3 4 public void PrintJob (objec T document) {5 queuelock.lock (); 6 7 try {8 long duration= (Long) (Math.random () *10000); 9 System.out.printf ("%s:printqueue:printing a Job during%d seconds\n", Thread.CurrentThread (). GetName (), (duration/ Thread.Sleep (Duration), one } catch (Interruptedexception e) { e.printstacktrace (); } finally { queuelock.unlock (); }16 }17}
Declares a lock, where Reentrantlock (a reentrant mutex) is an implementation of the lock interface
1 Private final Lock queuelock=new Reentrantlock ();
Then call the lock () method inside the function to declare the synchronization code block (critical section)
1 Queuelock.lock ();
Finally release the lock in the finally block, important!!!
1 Queuelock.unlock ();
Back to the top one of the biggest improvements to using read-write locks to implement synchronous data access lock mechanisms is the Readwritelock interface and his only implementation class Reentrantreadwritelock. This class has two locks, one is read operation Lock, one is write operation lock. When using a read lock, multiple threads can be allowed to access simultaneously, and only one thread is allowed to use a write lock. When a thread performs a write operation, other threads are not able to perform a read operation. When a write lock is invoked, a thread is used. Write-Operation Lock usage:
1 public void setprices (double Price1, double price2) {2 lock.writelock (). Lock (); 3 this.price1=price1;4 This.price2=price2;5 lock.writelock (). Unlock (); 6 }
Read Operation Lock:
1 public Double GetPrice1 () {2 lock.readlock (). Lock (); 3 double Value=price1; 4 lock.readlock (). Unlock (); 5 return value; 6 } 7 public double GetPrice2 () {8 lock.readlock (). Lock (); 9 Double value= Price2;10 lock.readlock (). Unlock (); return value;12 }
Back to top modify the fairness of the lock Reentrantlock and Reetrantreadwritelock constructors all contain a Boolean parameter fair. The default fair is false, which is non-fair mode. Fair mode: When there are many threads waiting for a lock, the lock selects a thread that waits for the longest time to enter the critical section. Unfair mode: When there are many threads waiting for a lock, the lock randomly selects a waiting area (ready state) for the thread to enter the critical section. Both modes apply to lock () and unlock () parties only. The Trylock () method of the lock interface does not put the thread into hibernation, and the Fair property does not affect this method. Back to the top use the multi-condition (Multri Condition) lock condition in the lock to make an analogy with the method of the critical section declared by the Synchronized keyword (wait (), notify (), Notifyall ()). The lock condition is declared through the Conditon interface. Condition provides a mechanism for suspending threads and waking threads. How to use:
1 private Condition lines; 2 private Condition space; 3 */4 public void Insert (String line) {5 lock.lock (), 6 try {7 while (Buffer.size ( ) = = maxSize) {8 space.await (); 9}10 Buffer.offer (line); System.ou t.printf ("%s:inserted line:%d\n", Thread.CurrentThread () GetName (), buffer.size ()); 13 Lines.signalall () (); catch (Interruptedexception e) {e.printstacktrace (); C} finally {1 7 Lock.unlock ();}19}20 public String Get () {string line=null;22 lock.lock () ; try {(buffer.size () = 0) && (haspendinglines ())) {lines.await ( );}27 if (Haspendinglines ()) {line = Buffer.poll (); 30 System.out.printf ("%s:line readed:%d\n", Thread.CurrentThread (). GetnAme (), buffer.size ()); Space.signalall ();}33} catch (Interruptedexception e) {34 E.printstacktrace (); finally {lock.unlock (); PNs}38 return line;39 }
Java Concurrent thread synchronization (synchronized and lock mechanism)