Because of the multi-threaded implementation, there may be many threads running at the same time when running a program, but the scheduling of threads is not visible, so it is not possible to know when a thread is running, for example, when you are sitting at a table holding a fork, going to the last piece of food in the fork, and when your fork is going to reach him The food suddenly disappears because your thread hangs and another diner enters and eats it, so this is the problem with multithreading, and for concurrent tasks, you need a way to prevent two threads from accessing a resource at the same time. Basically, all concurrency patterns use serialization to access shared resources in the case of thread collisions, which means that only one thread is allowed to access the shared resource at the given moment of the CPU, usually with a locking statement in front of the code, and once executed on the lock statement, result in a mutually exclusive effect, so this mechanism is often a mutex,
The first type of keyword synchronized : Java provides built-in support keyword synchronized for placing resource conflicts, and when code executes to a code fragment that is synchronized protected, it checks to see if the lock is available, then acquires the lock and releases the lock.
NOTE: * Shared resources are typically memory fragments that exist in an object shape, but can also be files, input \ Output ports, or printers, to control access to shared resources, first wrap it in an object, and then mark all the methods that will access the resource as synchronized. If a thread is in a call to a method that marks synchronized, before this method returns. All other threads that are calling any of the methods marked as synchronized in this class will be blocked.
Synchronized flaw: When a thread enters the synchronization method to obtain an object lock, other threads must wait or block when accessing the synchronization method of the object here, which is fatal for highly concurrent systems, which can easily cause a system crash. If a thread has a dead loop inside the synchronization method, it will never release the object lock, and the other threads will wait forever. This is a deadly problem.
Of course, synchronous and synchronous code blocks will have such a flaw, as long as the use of the Synchronized keyword will have such a risk and defect. Since this flaw cannot be avoided, the risk should be minimized. This is also the aspect of synchronous code blocks that are better than synchronous methods in some cases. For example in a method of a class: This class declares an object instance, Synobject so=new synobject (), a method that invokes this instance in a method So.testsy (), but calls this method requires synchronization. This method cannot be called simultaneously by multiple threads.
In this case, if the So.testsy () method is called directly with synchronized, then when a thread enters this method, the other synchronization methods of the object cannot be accessed by other threads. If this method takes a long time to execute, other threads will always block and affect the performance of the system.
If this is done with synchronized to modify the code block: synchronized (SO) {So.testsy ()}, then this method locks the object is so this object, and the object that executes this line of code is not related, when a thread executes this method, This has no effect on other synchronization methods, because the locks they hold are completely different.
all objects automatically contain a single lock, also called a monitor, when an arbitrary synchronized method is called on an object, the object is locked, and the other synchronized methods on that object are not invoked until the previous method call is complete and released. There is also a need to note that it is necessary to set the shared resource to private, and to prevent other threads from accessing the resource directly , it is useless to add a lock.
An object lock of one class is not associated with an object lock of another class, and when a thread obtains an object lock of Class A, it can also acquire an object lock of Class B.
A thread can then obtain the lock of an object multiple times, such as a method accessed by the synchronized tag that invokes the second synchronized tag on the same object. The latter calls another method on the same object that is synchronized marked, this happens, the virtual machine is responsible for tracking the number of times the object is locked, if an object is fully unlocked, its counter becomes 0, the first time the thread locks the object, the counter becomes 1, And then every time the same thread gets a lock on the object. Cumulative 1
Java object locks and class Locks: Java's object locks and class locks are basically consistent with the built-in locks in terms of locks, however, two locks are actually very different, object locks are used for object instance methods, or on an object instance, class locks are used for static methods of classes or for class objects on classes. We know that there can be many object instances of a class, but each class has only one class object, so object locks for different object instances do not interfere with each other, but each class has only one class lock. One thing to note, though, is that a class lock is just a conceptual thing, not a real one, it's just a way to help us understand the difference between a locked instance method and a static method.
define an object that shares a resource first Demo Object Lock
Package Test.thread.sx;public class BankAccount { //balance private int banlance = $; Query public int getbalance () { return banlance; } Withdrawal public void withdraw (int amount) { banlance = Banlance-amount; } Deposit public void deposit (int amount) { banlance = banlance + amount; } }
Then define the task method
Package Test.thread.sx;public class Tesmony implements Runnable {//All thread multithreaded threads share Runnable (interface object) and account object pri Vate BankAccount account = new BankAccount (); @Override public void Run () {for (int i = 0; i< 5; i++) {//Total withdrawals 5 times makewithdraw (100 ); Each withdrawal (Account.getbalance () < 0) {System.out.println ("☆" +thread.currentthread (). Get Name () + "Overdrawn!");}}} /** * Makewithdraw Account Withdrawal * @param amount Withdrawal amount <br/> * Print log record withdrawal process * */private synchronized void Makewithdraw (int amount) {if (account.getbalance () >= amount) {//If the balance is sufficient then withdrawals SYSTEM.O UT.PRINTLN ("☆" +thread.currentthread (). GetName () + "ready to withdraw money!"); try {thread.sleep (500); } catch (Interruptedexception e) {System.out.println (Thread.CurrentThread (). GetName () + "ready to withdraw, wait for 0.5s threads It's broken! " +e.getmessage ()); } account.withdraw (amount); SYSTEM.OUT.PRINTLN ("☆" +thread.currentthread (). GetName () + "complete" +amount+ "Withdrawals! Balance is" +account.getbalance ()); }else{//Insufficient balance will prompt System.out.println ("☆" + "balance insufficient to pay" +thread.currentthread (). GetName () +amount+ "withdrawals, balances As "+account.getbalance ()"); } } }
and test it.
Package Test.thread.sx;import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;public Class Tess {public static void Main (string[] args) { //define a task I made a mistake when I didn't understand the thread, that every new thread would give it a new task. Which is the new Tesmony object. There's no resource competition.
Because that's two objects. The competition is for an object and the mutex is also locked on the same object to appear mutually exclusive, tesmony target = new Tesmony (); Create Li Qi and his wife two threads implement the withdrawal (at the same time) thread LQ = new thread (target); Lq.setname ("Romeo"); Thread LQWF = new Thread (target); Lqwf.setname ("Juliet"); Call the Start () method of the Thread object, start the thread, execute the Run () method (OS) Lq.start (); Lqwf.start (); } }
The second type of Java also provides another way to display the lock the way This is also a lock that is invoked with a spoof, and uses the lock and Unlock method identifies a critical resource, and the synchronized the difference between the keywords when we use synchronized keyword tagged code fragment when there are some errors throws an exception but there is no chance to do any remedial work, but using lock object method to add lock when unlocking, we can use the Finnaly words to do some processing. Then the above code can do so he modifies
Package Test.thread.sx;import Java.util.concurrent.locks.lock;import Java.util.concurrent.locks.ReentrantLock; public class Tesmony implements Runnable {private lock lock = new Reentrantlock (); All thread multithreading threads share Runnable (interface object) and account object Private BankAccount account = new BankAccount (); @Override public void Run () {for (int i = 0; i < 5; i++) {//Total withdrawals 5 times makewithdraw (100);//per withdrawal 10 0 if (account.getbalance () < 0) {System.out.println ("☆" + thread.currentthread (). GetName () + "Overdrawn!"); }}}/** * Makewithdraw account Withdrawal * * @param amount * Withdrawal amount <br/> * Print log record withdrawal process */private void Makewithdraw (int amount) {lock.lock (); try {if (account.getbalance () >= amount) {//If the balance is sufficient then the withdrawal System.out.println ("☆" + Thread.curr Entthread (). GetName () + "ready to withdraw money!"); Thread.Sleep (500); Account.witHdraw (amount); SYSTEM.OUT.PRINTLN ("☆" + thread.currentthread (). GetName () + "done" + amount + "withdrawals!" Balance is "+ account." GetBalance ()); } else {//insufficient balance prompts System.out.println ("☆" + "balance insufficient to pay" + thread.currentthread (). GetName () + Amount + "fetch The balance is "+ account.getbalance ()"); }} catch (Interruptedexception e) {System.err.println ("Interrupt Please Wait"); } finally {Lock.unlock (); } }}
Java solves shared resource competition