java synchronized keyword study notes

The synchronized (synchronized lock) keyword is used to solve the problem of competition for shared resources. Basically all concurrency modes use serialized access to shared resources when solving thread conflicts . This means that at any time, only one task is allowed to access shared resources . Usually this is achieved by adding a lock statement before the code, which allows only one task to run this code at a given moment. Because the lock statement produces a mutually exclusive effect, this mechanism is often called a mutual exclusion .

To control access to shared resources, you must first install it into an object. Then mark all methods that want to access this resource as synchronized. If a task is in a call to a method marked as synchronized, before the thread returns from the method, all other methods to be called in the class marked as synchronized will be in a blocked state .

synchronized void f(){
    
    }
synchronized void g(){
    
    }

All objects automatically contain a single lock (also called a monitor) .

When using concurrency, it is very important to set the domain to private. Otherwise, the synchronized keyword cannot prevent other tasks from directly accessing the domain, which will cause conflicts .

A task can acquire the lock of an object multiple times , which is manifested in calling another method marked as synchronized in a method marked as synchronized, or even multiple layers. The JVM will count the number of call levels, and the count will be set to 0 until the lock is completely released.

For each class, there is also a lock (as part of the Class object), so the synchronized static method can prevent concurrent access to static data within the scope of the class.

Every method of accessing critical shared resources must be synchronized, otherwise they will not work correctly.

public abstract class IntGenerator {
    
    
    private volatile boolean canceled=false;
    public abstract int next();
    public void cancel() {
    
    canceled=true;}
    public boolean isCanceled() {
    
    return canceled;}
}
public class EvenChecker implements Runnable{
    
    
    private IntGenerator generator;
    private final int id;
    public EvenChecker(IntGenerator g,int ident) {
    
    
    	generator=g;
    	id=ident;
    }
	@Override
	public void run() {
    
    
		// TODO Auto-generated method stub
		while(!generator.isCanceled()) {
    
    
			int val=generator.next();
			if(val%2!=0) {
    
    
				System.out.println(val+" is not even");
			}
			generator.cancel();
		}
	}
    public static void test(IntGenerator gp,int count) {
    
    
    	System.out.println("Press Control-c to exit");
    	ExecutorService exec=Executors.newCachedThreadPool();
    	for(int i=0;i<count;i++) {
    
    
    		exec.execute(new EvenChecker(gp,i));
    	}
    	exec.shutdown();
    }
    public static void test(IntGenerator gp) {
    
    
    	test(gp,10);
    }
}

public class EvenGenerator extends IntGenerator{
    
    
    private int currentEvenValue=0;
    public synchronized int next() {
    
    
    	++currentEvenValue;
    	Thread.yield();
    	++currentEvenValue;
    	return currentEvenValue;
    }
	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
        EvenChecker.test(new EvenGenerator());
	}

}

If you remove the synchronized keyword and concession statement that modifies the next() method in EvenGenertor, it will cause confusion in the execution of multiple threads. That is, a thread does not perform two self-add operations.

Guess you like

Origin blog.csdn.net/weixin_43916777/article/details/104263308