1. Multi-thread synchronization:
1.1. Synchronization mechanism:
In multi-threading, there may be multiple threads trying to access a limited resource, and this must be prevented. Therefore, a synchronization mechanism is introduced: when a thread uses a resource, it is locked, so that other threads cannot access that resource until it is unlocked.
1.2. Examples of shared member variables:
Member variables and local variables:
Member variables:
If a variable is a member variable, then multiple threads operate on the member variables of the same object, and these multiple threads are shared A member variable.
Local variables:
If a variable is a local variable, then multiple threads operate on the same object, and each thread will have a copy of the local variable. The local variables between them do not affect each other.
The following is an example:
Thread class that implements Runnable:
class MyThread3 implements Runnable{ //两个线程操作同一个对象,共享成员变量 //int i; @Override public void run() { //两个线程操作同一个对象,各自保存局部变量的拷贝 int i = 0; while(i<100){ System.out.println(i); i++; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Use two threads to operate the same object in the main method:
public static void main(String[] args) { MyThread3 myThread = new MyThread3(); //下面两个线程对同一个对象(Runnable的实现类对象)进行操作 Thread thread = new Thread(myThread); Thread thread2 = new Thread(myThread); //各自保存局部变量的拷贝,互不影响,输出200个数字 thread.start(); thread2.start(); }
If i is changed into a member variable here, 100 numbers will be output.
1.3. Read errors caused by shared resources
The following is an example. Two threads share a Number object and obtain data through the getNumber method of the Number class. When reading and rewriting the data, a repeated read operation is discovered:
First of all. Create a Number class:
class Number{ private int number = 10; public String getNumber(int i){ if(number > 0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } number -= i; return "取出"+i+"成功,剩余数量:"+number; } return "取出"+i+"失败,剩余数量:"+number; } }
Thread class, the private properties in the thread class contain a reference to the Number class:
class MyThread4 extends Thread{ //两个线程操作同一个对象,共享成员变量 Number number; public MyThread4(Number number){ this.number = number; } @Override public void run() { System.out.println(number.getNumber(8)); } }
Create two thread classes in the main function, contain a reference to the same Number class instance:
public static void main(String[] args) { Number number = new Number(); //两个线程操作同一个对象,共享对象number的成员变量number MyThread4 myThread = new MyThread4(number); MyThread4 myThread2 = new MyThread4(number); myThread.start(); myThread2.start(); }
In this way, when the first thread reads the number variable in Number, it saves it first and then sleeps for 0.1 seconds. Then the second thread reads the number variable and saves it. At this time, the two threads save the same number and modify it. time, which results in the same number being modified twice.
2. Implementation of synchronization mechanism:
Synchronized has always been a veteran role in multi-threaded concurrent programming. Many people will call it a heavyweight lock. However, with various optimizations of Synchronized in Java SE1.6, In some cases it is not so heavy"
Every object in Java can be used as a lock.
For synchronized methods, the lock is the current instance object.
For static synchronized methods, the lock is the Class object of the current object.
For Synchronized method block, the lock is the object configured in Synchonized brackets.
When a thread tries to access the synchronized code block, it must first obtain the lock, and the lock must be released when exiting or throwing an exception.
2.1. Use the synchronized keyword to create a synchronized method. :
Use the synchronized keyword. The method modified by this keyword is called a synchronized method.
Every object in Java has a lock or monitor. When accessing the synchronized method of an object, it means that the object is locked. , instead of just locking this method.
In this way, if the synchronized method of an object is executed by a thread, other threads cannot access any synchronized method of the object (but other non-synchronized methods can be called until that time). The synchronized method is executed.
Static synchronized method calling situation:
When the static synchronized method of an object is called, it is not the object where the synchronized method is located, but the Class object corresponding to the object where the synchronized method is located. The thread cannot call other static synchronized methods of this class, but it can call non-static synchronized methods.
Conclusion: Execute the static synchronized method to lock the object where the method is located, and execute the non-static synchronized method to lock the Class object corresponding to the method.
The following is an example of multi-thread calling a static method. Since the Class object corresponding to the object where the method is located is locked, other threads cannot call other static synchronized methods of the object where the method is located:
/** * 定义一个类,包含了线程类需要调用的方法 */ class Compute1{ //这时如果某个线程调用该方法, //将锁定synchronized方法所在对象对应的class对象, //而不是锁定synchronized方法所在对象 public synchronized static void execute(){ for(int i = 0; i<100; i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("compute1:execute1 " + i++); } } public synchronized static void execute2(){ for(int i = 0; i<100; i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("compute1:execute2 " + i++); } } }
In the main method, two threads call the same one respectively Two static synchronized methods of the object:
public static void main(String[] args) { Compute1 com = new Compute1(); Thread thread1 = new Thread1(com); Thread thread2 = new Thread2(com); thread1.start(); thread2.start(); }
Only one static method can be called at a time until execution is completed
2.2. Use synchronized to create a synchronized code block:
By using a synchronized synchronized code block, an object is locked and the object is available as a synchronized code block. The execution flag to achieve synchronization effect:
/** * 定义一个类,包含了线程类需要调用的方法 */ class Compute1{ //通过同步代码块锁定object1对象进行锁定了其他同样的synchronized代码块 private Object object1 = new Object(); public void execute(){ synchronized(object1){ for(int i = 0; i<100; i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("compute1:execute1 " + i++); } } } public synchronized void execute2(){ synchronized(object1){ for(int i = 0; i<100; i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("compute1:execute2 " + i++); } } } }
If you want to use synchronized synchronized code block to achieve the same effect as using synchronized method, you can lock this reference:
synchronized(this){ … }
2.3, the difference between synchronized method and synchronized synchronized code block:
The synchronized synchronized code block only locks the code block, and the code outside the code block can still be accessed.
The synchronized method is a coarse-grained concurrency control. Only one thread can execute the synchronized method at a certain time.
Synchronized synchronized code block is a fine-grained concurrency control. Only the code in the block will be synchronized. Code outside the code block can be accessed by other threads at the same time.
For more detailed explanations of thread synchronization methods in Java multi-threaded programming, please pay attention to the PHP Chinese website!