1. Synchronization method
There is a method to modify synchronized keywords.
Since each object in java has a built-in lock, when modifying the method with this keyword,
Built-in locks protect the entire method. Before calling this method, you need to obtain a built-in lock, otherwise it will be in a blocking state.
Codes such as:
public synchronized void save(){}
Note: The synchronized keyword can also modify static methods. If the static method is called at this time, the entire class will be locked.
public class Bank { private int count =0;//Account balance //Save money public synchronized void addMoney(int money){ count +=money; (()+"Save in:"+money); } // Withdraw money public synchronized void subMoney(int money){ if(count-money < 0){ ("Insufficient balance"); return; } count -=money; (+()+"take out:"+money); } //Inquiry public void lookMoney(){ ("Account Balance:"+count); } }
2. Synchronize code blocks
That is, there is a statement block modified by synchronized keyword.
The statement block modified by this keyword will be automatically added with a built-in lock to achieve synchronization.
Codes such as:
synchronized(object){
}
Note: Synchronization is a high-overhead operation, so synchronized content should be minimized.
Usually there is no need to synchronize the entire method, just use the synchronized code block to synchronize the key code.
public class Bank { private int count =0;//Account balance //Save money public void addMoney(int money){ synchronized (this) { count +=money; } (()+"Save in:"+money); } // Withdraw money public void subMoney(int money){ synchronized (this) { if(count-money < 0){ ("Insufficient balance"); return; } count -=money; } (+()+"take out:"+money); } //Inquiry public void lookMoney(){ ("Account Balance:"+count); } }
This also realizes thread synchronization, and its operation efficiency is higher than method synchronization efficiency. Synchronization is a high-overhead operation, so the synchronized content should be minimized. Usually there is no need to synchronize the entire method, just use the synchronized code block to synchronize the key code. .
3. Use special domain variables (volatile) to achieve thread synchronization
Keywords provide a lock-free mechanism for accessing domain variables,
b. Using volatile to modify the domain is equivalent to telling the virtual machine that the domain may be updated by other threads.
c. Therefore, every time you use the field, you have to recalculate it, instead of using the value in the register.
No atomic operations are provided, and it cannot be used to modify variables of final type.
The code is as follows:
package ; /** * Created by HJS on 2017/8/12. */ public class Bank { private volatile int count =0;//Account balance //Save money public void addMoney(int money){ synchronized (this) { count +=money; } (()+"Save in:"+money); } // Withdraw money public void subMoney(int money){ synchronized (this) { if(count-money < 0){ ("Insufficient balance"); return; } count -=money; } (+()+"take out:"+money); } //Inquiry public void lookMoney(){ ("Account Balance:"+count); } }
At this time, the order is messed up again, indicating that there is another problem with synchronization, because volatile cannot guarantee the atomic operation, so volatile cannot replace synchronized. In addition, volatile will organize the compiler to optimize the code, so if you can use it, it won't apply. Its principle is that every time a thread wants to access a variable modified by volatile, it is read from memory, rather than from the cache, so the variable value accessed by each thread is the same. This ensures synchronization.
4. Use reentry lock to achieve thread synchronization
A new package has been added to JavaSE5.0 to support synchronization. The ReentrantLock class is a reentrant, mutually exclusive lock that implements the Lock interface. It has the same basic behavior and semantics as using synchronized methods and fast, and extends its capabilities.
Common methods of the ReenreantLock class are:
ReentrantLock(): Create a ReentrantLock instance
lock() : Obtain the lock
unlock() : Release the lock
Note: ReentrantLock() also has a constructor that can create fair locks, but it is not recommended to use it because it can greatly reduce the program operation efficiency.
The code is modified as follows:
public class Bank { private int count = 0;// Account balance //This lock needs to be declared private Lock lock = new ReentrantLock(); // Save money public void addMoney(int money) { ();//Lock try{ count += money; (() + "Save in:" + money); }finally{ ();//Unlock } } // Withdraw money public void subMoney(int money) { (); try{ if (count - money < 0) { ("Insufficient balance"); return; } count -= money; (+() + "take out:" + money); }finally{ (); } } // Query public void lookMoney() { ("Account Balance:" + count); } }
Note: About the selection of Lock objects and synchronized keywords:
a. It is best not to use both, and use a mechanism provided by a package.
Can help users handle all lock-related code.
b. If the synchronized keyword can meet the needs of users, use synchronized because it can simplify the code.
c. If more advanced functions are needed, use the ReentrantLock class. At this time, be careful to release the lock in time, otherwise a deadlock will occur. Usually, the lock is released in finally code.
This is the end of this article about several ways to implement java synchronization. For more related java synchronization content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!