Synchronization

The introduction of synchronization

There are two built-in synchronized syntaxes in the java language: synchronized code blocks and synchronized methods (static methods and non-static methods) can solve thread safety issues

First, synchronized changes parallel to serial, which will of course affect the execution efficiency of the program, and the execution speed will be affected. Secondly, the blocking of the synchronized operation thread means that the operating system controls the CPU core to switch the context. This switch itself is also time-consuming. So using the synchronized keyword will reduce the efficiency of the program.

problem

Thread safety is an important concern in concurrent programming. It should be noted that there are two main causes of thread safety problems. One is the existence of shared data (also called critical resources), and the other is the existence of multiple threads operating and sharing data.

The solution to the error

When there are multiple threads operating shared data, it is necessary to ensure that there is one and only one thread operating shared data at the same time, and other threads must wait until the thread has processed the data before proceeding. This method has a name called mutual exclusion lock, which can A lock that achieves the purpose of mutual exclusion access, that is to say, when a shared data is added to the mutex by the currently accessing thread, at the same moment, other threads can only be in a waiting state until the current thread finishes processing the lock and releases the lock

  • In Java, every object has an object lock, which is actually a tag value on the object header.
  • The goal of synchronization is actually to achieve the purpose of thread queuing execution

- 1. The synchronization method
to add synchronization constraints -synchronized method for the modification of critical resources

//临界资源---被多个线程所共享操作的对象
    public class OperNum {
    
    
    	private int target;//操作的数据
    	//针对操作数据的方法
    	public synchronized void add() {
    
    //synchronized方法的同步锁为当前对象
    		target++;
    		System.out.println(Thread.currentThread().getName()+"add...."+target);
    	}
    	public synchronized void sub() {
    
    
    		target--;
    		System.out.println(Thread.currentThread().getName()+"sub...."+target);
    	}
    }

Principle: When a thread executes the add method, other threads cannot execute the add or sub method [Neither the synchronized method can execute, because the synchronized keyword introduces a mutex lock, and only the thread that owns the lock can execute the synchronized method, and other threads Can only block waiting], synchronized is a reentry lock, that is, the current thread can execute other synchronized methods, but other threads cannot execute the synchronized method in the current object, and can execute methods without synchronized constraints

2. Synchronization code block The
lock is actually designated manually, it is recommended to use

synchronized(锁){}

 public class MyThread extends Thread {
    
    
    	private static int target = 0; // 操作目标,临界资源
    	private boolean flag = true; // 不是临界资源
    	// 定义一个互斥锁
    	private static Object lock = new Object();
    	public MyThread(boolean flag) {
    
    
    		this.flag = flag;
    	}
    	public void run() {
    
    
    		for (int i = 0; i < 50; i++) {
    
    
    			//synchronized (lock) 可以保证{}中的代码执行具备原子性
    			synchronized (lock) {
    
    
    				if (flag) target++;
    				else target--;
    				System.out.println(Thread.currentThread().getName() + (flag ? "add" : "sub") + "...." + target);
    			}
    		}
    	}
    	public static void main(String[] args) {
    
    
    		for(int i=0;i<4;i++) {
    
    
    			new MyThread(i%2==0).start();
    		}
    	}
    }

3. Synchronous static methods Use
the current class object as a lock, and all static methods are mutually exclusive

  • And non-static methods are not mutually exclusive, because the lock of the non-static synchronized method is the current object, not the class lock
//临界资源
public class OperNum {
    
    
	private static int target=10;//操作的数据
	//针对操作数据的方法
	public synchronized static void add() {
    
    
		target++;
		System.out.println(Thread.currentThread().getName()+"add...."+target);
	}
	public synchronized static void sub() {
    
    
		target--;
		System.out.println(Thread.currentThread().getName()+"sub...."+target);
	}
}

Guess you like

Origin blog.csdn.net/qq_45874107/article/details/113876210