Java learning notes-five methods of multi-thread synchronization, java learning notes

Source: Internet
Author: User
Tags to domain

Java learning notes-five methods of multi-thread synchronization, java learning notes
I. Introduction

A few days ago, the interview was abused by the master and a lot of basic knowledge had to be taken up again. If you don't talk much about it, go to the topic.

Ii. Why thread synchronization?

Because when we have multiple threads that want to access a variable or object at the same time, if there are both read and write operations in these threads, it will lead to confusion of the variable value or object status, this causes program exceptions. For example, if a bank account is operated by two threads at the same time, one takes 100 yuan and the other saves 100 yuan. Assume that there are 0 accounts. What will happen if both the money withdrawal thread and the deposit thread occur? Fail to get the money. The account balance is 100. The money is successfully obtained, and the account balance is 0. Which one is it? It is hard to say clearly. Therefore, multithreading synchronization is to solve this problem.

3. Code for different steps

Bank. java

  1. PackagethreadTest;
  2.  
  3. /**
  4. * @ Authorww
  5. *
  6. */
  7. PublicclassBank {
  8.  
  9. Privateintcount = 0; // account balance
  10.  
  11. // Save money
  12. PublicvoidaddMoney (intmoney ){
  13. Count + = money;
  14. System. out. println (System. currentTimeMillis () + "saved in:" + money );
  15. }
  16.  
  17. // Get the money
  18. PublicvoidsubMoney (intmoney ){
  19. If (count-money <0 ){
  20. System. out. println ("insufficient balance ");
  21. Return;
  22. }
  23. Count-= money;
  24. System. out. println (+ System. currentTimeMillis () + "retrieve:" + money );
  25. }
  26.  
  27. // Query
  28. PublicvoidlookMoney (){
  29. System. out. println ("account balance:" + count );
  30. }
  31. }

SyncThreadTest. java

  1. PackagethreadTest;
  2.  
  3.  
  4. PublicclassSyncThreadTest {
  5.  
  6. Publicstaticvoidmain (Stringargs []) {
  7. FinalBankbank = newBank ();
  8.  
  9. Threadtadd = newThread (newRunnable (){
  10.  
  11. @ Override
  12. Publicvoidrun (){
  13. // TODOAuto-generatedmethodstub
  14. While (true ){
  15. Try {
  16. Thread. sleep (1000 );
  17. } Catch (InterruptedExceptione ){
  18. // TODOAuto-generatedcatchblock
  19. E. printStackTrace ();
  20. }
  21. Bank. addMoney (100 );
  22. Bank. lookMoney ();
  23. System. out. println ("n ");
  24.  
  25. }
  26. }
  27. });
  28.  
  29. Threadtsub = newThread (newRunnable (){
  30.  
  31. @ Override
  32. Publicvoidrun (){
  33. // TODOAuto-generatedmethodstub
  34. While (true ){
  35. Bank. subcurrency (100 );
  36. Bank. lookMoney ();
  37. System. out. println ("n ");
  38. Try {
  39. Thread. sleep (1000 );
  40. } Catch (InterruptedExceptione ){
  41. // TODOAuto-generatedcatchblock
  42. E. printStackTrace ();
  43. }
  44. }
  45. }
  46. });
  47. Tsub. start ();
  48.  
  49. Tadd. start ();
  50. }
  51.  
  52.  
  53.  
  54. }

The code is very simple. I will not explain it. What is the running result? If some of them are intercepted, is it messy.

  1. Insufficient balance
  2. Account Balance: 0
  3.  
  4.  
  5. Insufficient balance
  6. Balance: 100
  7.  
  8.  
  9. 1441790503354: 100
  10. Balance: 100
  11.  
  12.  
  13. 1441790504354: 100
  14. Balance: 100
  15.  
  16.  
  17. 1441790504354 fetch: 100
  18. Balance: 100
  19.  
  20.  
  21. 1441790505355: 100
  22. Balance: 100
  23.  
  24.  
  25. 1441790505355 fetch: 100
  26. Balance: 100
4. Use the synchronization code (1) synchronization method:

There is also a method for modifying the synchronized keyword. Because every object in java has a built-in lock, when this keyword is used to modify the method, the built-in lock will protect the entire method. You must obtain the built-in lock before calling this method. Otherwise, the lock is blocked.

Modified Bank. java

  1. PackagethreadTest;
  2.  
  3. /**
  4. * @ Authorww
  5. *
  6. */
  7. PublicclassBank {
  8.  
  9. Privateintcount = 0; // account balance
  10.  
  11. // Save money
  12. PublicsynchronizedvoidaddMoney (intmoney ){
  13. Count + = money;
  14. System. out. println (System. currentTimeMillis () + "saved in:" + money );
  15. }
  16.  
  17. // Get the money
  18. PublicsynchronizedvoidsubMoney (intmoney ){
  19. If (count-money <0 ){
  20. System. out. println ("insufficient balance ");
  21. Return;
  22. }
  23. Count-= money;
  24. System. out. println (+ System. currentTimeMillis () + "retrieve:" + money );
  25. }
  26.  
  27. // Query
  28. PublicvoidlookMoney (){
  29. System. out. println ("account balance:" + count );
  30. }
  31. }

Let's look at the running result:

  1. Insufficient balance
  2. Account Balance: 0
  3.  
  4.  
  5. Insufficient balance
  6. Account Balance: 0
  7.  
  8.  
  9. 1441790837380: 100
  10. Balance: 100
  11.  
  12.  
  13. 1441790838380 fetch: 100
  14. Account Balance: 0
  15. 1441790838380: 100
  16. Balance: 100
  17.  
  18.  
  19.  
  20.  
  21. 1441790839381 fetch: 100
  22. Account Balance: 0

I can understand it in an instant.

Note: The synchronized keyword can also modify the static method. If you call this static method, the entire class will be locked.

(2) Synchronous Code Block

There are statement blocks modified by the synchronized keyword. The statement block modified by this keyword is automatically added with a built-in lock to achieve synchronization.

The Bank. java code is as follows:

  1. PackagethreadTest;
  2.  
  3. /**
  4. * @ Authorww
  5. *
  6. */
  7. PublicclassBank {
  8.  
  9. Privateintcount = 0; // account balance
  10.  
  11. // Save money
  12. PublicvoidaddMoney (intmoney ){
  13.  
  14. Synchronized (this ){
  15. Count + = money;
  16. }
  17. System. out. println (System. currentTimeMillis () + "saved in:" + money );
  18. }
  19.  
  20. // Get the money
  21. PublicvoidsubMoney (intmoney ){
  22.  
  23. Synchronized (this ){
  24. If (count-money <0 ){
  25. System. out. println ("insufficient balance ");
  26. Return;
  27. }
  28. Count-= money;
  29. }
  30. System. out. println (+ System. currentTimeMillis () + "retrieve:" + money );
  31. }
  32.  
  33. // Query
  34. PublicvoidlookMoney (){
  35. System. out. println ("account balance:" + count );
  36. }
  37. }

The running result is as follows:

  1. Insufficient balance
  2. Account Balance: 0
  3.  
  4.  
  5. 1441791806699: 100
  6. Balance: 100
  7.  
  8.  
  9. 1441791806700 fetch: 100
  10. Account Balance: 0
  11.  
  12.  
  13. 1441791807699: 100
  14. Balance: 100

The effect is similar to method 1.

Note: synchronization is a highly open operation, so you should minimize the amount of synchronization content. Generally, there is no need to synchronize the entire method. Use the synchronized code block to synchronize key code.

(3) use special domain variables (volatile) for Thread Synchronization

A. The volatile keyword provides a lock-free mechanism for access to domain variables.
B. Modifying the domain using volatile is equivalent to telling the virtual machine that the domain may be updated by other threads.
C. Therefore, each time you use this field, you need to recalculate it instead of using the value in the register.
D. volatile does not provide any atomic operations, nor can it be used to modify final-type variables.

The Bank. java code is as follows:

  1. PackagethreadTest;
  2.  
  3. /**
  4. * @ Authorww
  5. *
  6. */
  7. PublicclassBank {
  8.  
  9. Privatevolatileintcount = 0; // account balance
  10.  
  11. // Save money
  12. PublicvoidaddMoney (intmoney ){
  13.  
  14. Count + = money;
  15. System. out. println (System. currentTimeMillis () + "saved in:" + money );
  16. }
  17.  
  18. // Get the money
  19. PublicvoidsubMoney (intmoney ){
  20.  
  21. If (count-money <0 ){
  22. System. out. println ("insufficient balance ");
  23. Return;
  24. }
  25. Count-= money;
  26. System. out. println (+ System. currentTimeMillis () + "retrieve:" + money );
  27. }
  28.  
  29. // Query
  30. PublicvoidlookMoney (){
  31. System. out. println ("account balance:" + count );
  32. }
  33. }

What is the running effect?

  1. Insufficient balance
  2. Account Balance: 0
  3.  
  4.  
  5. Insufficient balance
  6. Balance: 100
  7.  
  8.  
  9. 1441792010959: 100
  10. Balance: 100
  11.  
  12.  
  13. 1441792011960 fetch: 100
  14. Account Balance: 0
  15.  
  16.  
  17. 1441792011961: 100
  18. Balance: 100

Are you confused. Why? Because volatile cannot guarantee atomic operations, volatile cannot replace synchronized. In addition, volatile will organize the compiler to optimize the code, so it is not applicable if it is not used. The principle is that every time a thread wants to access a variable modified by volatile, it reads data from the memory instead of the memory cache. Therefore, the variable values accessed by each thread are the same. This ensures synchronization.

(4) use the re-entry lock for Thread Synchronization

Added a java. util. concurrent package in JavaSE5.0 to support synchronization. The ReentrantLock class is a reentrant and mutex Lock that implements the Lock interface. It has the same basic behavior and semantics as using the synchronized Method and fast, and extends its capabilities.
Common ReenreantLock methods include:
ReentrantLock (): Creates a ReentrantLock instance.
Lock (): Get the lock
Unlock (): Release the lock
Note: ReentrantLock () also has a constructor that can create a fair lock. However, it is not recommended because it can greatly reduce the program running efficiency.
The Bank. java code is modified as follows:

  1. PackagethreadTest;
  2.  
  3. Importjava. util. concurrent. locks. Lock;
  4. Importjava. util. concurrent. locks. ReentrantLock;
  5.  
  6. /**
  7. * @ Authorww
  8. *
  9. */
  10. PublicclassBank {
  11.  
  12. Privateintcount = 0; // account balance
  13.  
  14. // The lock needs to be declared
  15. PrivateLocklock = newReentrantLock ();
  16.  
  17. // Save money
  18. PublicvoidaddMoney (intmoney ){
  19. Lock. lock (); // lock
  20. Try {
  21. Count + = money;
  22. System. out. println (System. currentTimeMillis () + "saved in:" + money );
  23.  
  24. } Finally {
  25. Lock. unlock (); // unlock
  26. }
  27. }
  28.  
  29. // Get the money
  30. PublicvoidsubMoney (intmoney ){
  31. Lock. lock ();
  32. Try {
  33.  
  34. If (count-money <0 ){
  35. System. out. println ("insufficient balance ");
  36. Return;
  37. }
  38. Count-= money;
  39. System. out. println (+ System. currentTimeMillis () + "retrieve:" + money );
  40. } Finally {
  41. Lock. unlock ();
  42. }
  43. }
  44.  
  45. // Query
  46. PublicvoidlookMoney (){
  47. System. out. println ("account balance:" + count );
  48. }
  49. }

How is the running effect?

  1. Insufficient balance
  2. Account Balance: 0
  3.  
  4.  
  5. Insufficient balance
  6. Account Balance: 0
  7.  
  8.  
  9. 1441792891934: 100
  10. Balance: 100
  11.  
  12.  
  13. 1441792892935: 100
  14. Balance: 200
  15.  
  16.  
  17. 1441792892954 fetch: 100
  18. Balance: 100

The effect is similar to the previous two methods.

If the synchronized keyword can meet your needs, use synchronized because it simplifies code. If you need more advanced functions, use the ReentrantLock class. Pay attention to releasing the lock in time. Otherwise, a deadlock occurs. Usually, the lock is released in finally code.

(5) use local variables for Thread Synchronization

The Bank. java code is as follows:

  1. PackagethreadTest;
  2.  
  3.  
  4. /**
  5. * @ Authorww
  6. *
  7. */
  8. PublicclassBank {
  9.  
  10. PrivatestaticThreadLocal <Integer> count = newThreadLocal <Integer> (){
  11.  
  12. @ Override
  13. ProtectedIntegerinitialValue (){
  14. // TODOAuto-generatedmethodstub
  15. Return0;
  16. }
  17.  
  18. };
  19.  
  20.  
  21. // Save money
  22. PublicvoidaddMoney (intmoney ){
  23. Count. set (count. get () + money );
  24. System. out. println (System. currentTimeMillis () + "saved in:" + money );
  25.  
  26. }
  27.  
  28. // Get the money
  29. PublicvoidsubMoney (intmoney ){
  30. If (count. get ()-money <0 ){
  31. System. out. println ("insufficient balance ");
  32. Return;
  33. }
  34. Count. set (count. get ()-money );
  35. System. out. println (+ System. currentTimeMillis () + "retrieve:" + money );
  36. }
  37.  
  38. // Query
  39. PublicvoidlookMoney (){
  40. System. out. println ("account balance:" + count. get ());
  41. }
  42. }

Running effect:

  1. Insufficient balance
  2. Account Balance: 0
  3.  
  4.  
  5. Insufficient balance
  6. Account Balance: 0
  7.  
  8.  
  9. 1441794247939: 100
  10. Balance: 100
  11.  
  12.  
  13. Insufficient balance
  14. 1441794248940: 100
  15. Account Balance: 0
  16.  
  17.  
  18. Balance: 200
  19.  
  20.  
  21. Insufficient balance
  22. Account Balance: 0
  23.  
  24.  
  25. 1441794249941: 100
  26. Balance: 300

After reading the running effect, I was confused at the beginning. How can I just save it? Let's take a look at the principle of ThreadLocal:

If ThreadLocal is used to manage a variable, each thread that uses the variable obtains a copy of the variable. The copies are independent of each other, so that each thread can modify its own copy of the variable at will, it does not affect other threads. Now, I understand that each thread runs a copy. That is to say, there are two accounts for saving and obtaining money, and the same knowledge name is used. So the above effect will occur.

ThreadLocal and synchronization mechanism
A. The ThreadLocal and synchronization mechanisms are designed to solve the access conflicts of the same variables in multiple threads.

B. The former adopts the "space for Time" method, and the latter adopts the "Time for space" method.

I understand it now. Each has its own advantages and disadvantages and has its own applicable scenarios. Manual, eat now.

Q: customized IT education platform, one-to-one service, Q & A. Official Website for developing programming social headlines: www.wenaaa.com

QQ Group 290551701 has gathered many Internet elites, Technical Directors, architects, and project managers! Open-source technology research, welcome to the industry, Daniel and beginners interested in IT industry personnel!

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.