Java learning thread safety

Thread synchronization (thread safe processing Synchronized)

Two ways of thread synchronization:

1. Synchronized code block

2. Synchronization method

Synchronized code block

Synchronized code block : add synchronized to the code block declaration

synchronized ( lock object ) {

Code that may create thread safety issues

}

The lock object in the synchronized code block can be any object; however, when multiple threads are used, the same lock object must be used to ensure thread safety.

package com.oracle.demo01;

/*Format:
 * synchronized(any object){
 * Shared data to be manipulated by the thread
 * }
 * Arbitrary objects: synchronization objects, synchronization locks, object monitors
 * How can synchronization guarantee security?
 * Threads without locks cannot execute, they can only wait
 *  
 * After the thread obtains CPU resources, it wants to execute the content of the synchronized code block. It first checks to see if there is a synchronization lock.
 * If there is, then your thread acquires the lock, and then enters the synchronized block to execute the code, although in the synchronized block, the thread sleeps
 * When this thread is sleeping, other threads obtain resources and want to execute the synchronized code block. It first checks to see if there is a lock, and then, there is no lock
 * it's blocked right after the block, just wait
 * When the sleeping thread finishes sleeping, it gets up and continues to execute the content in the code block. After all the content in the code block is executed, the lock is released.
 * Then other threads get the lock and can continue to execute
 *  
 * Thread-safe, then the execution speed will be slower
 * */
public class Ticket implements Runnable {
	private int ticket = 100;
	Object obj = new Object();

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			synchronized (obj) {
				if (ticket > 0) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace ();
					}
					System.out.println(Thread.currentThread().getName() + "sale" + (ticket--) + "ticket");
				}
			}

		}
	}

}
package com.oracle.demo01;

public class Test {
	public static void main(String[] args) {
		Ticket t = new Ticket();
		Thread t0 = new Thread(t);
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t0.start();
		t1.start();
		t2.start();
	}
}

Synchronized method

Synchronized method: add synchronized to the method declaration

public synchronized void method(){

    Code that may create thread safety issues

}

The lock object in the synchronized method is this

Static synchronized method : add static synchronized to the method declaration

public static synchronized void method(){

Code that may create thread safety issues

}

package com.oracle.demo02;

/*
 * Are there locks in synchronized methods?
 *There is a lock, the object lock in the synchronization method is that the object of this class refers to this
 *StringBuffer: The reason why it is safe is because there are synchronization methods in it. As long as there is synchronization, it is safe and slow.
 *StringBuilder: unsafe, because there is no synchronization, it is fast
 *
 *If your synchronized method is static, is there a lock? Is it still this?
 *There is a lock, not this, but this class itself, that is, ticket.class This class class name.class
 * */
public class Ticket implements Runnable {
	private int ticket = 100;
	Object obj = new Object();

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			//synchronized (this)
			synchronized (obj) {
               method();
			}

		}
	}
   //Synchronized code block, the code is more concise
	public synchronized void method() {
		if (ticket > 0) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace ();
			}
			System.out.println(Thread.currentThread().getName() + "sale" + (ticket--) + "ticket");
		}
	}
}
package com.oracle.demo01;

public class Test {
	public static void main(String[] args) {
		Ticket t = new Ticket();
		Thread t0 = new Thread(t);
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t0.start();
		t1.start();
		t2.start();
	}
}

Lock interface

The Lock  implementation provides a wider range of locking operations than can be obtained using synchronized  methods and statements.

Common method:

package com.oracle.demo03;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
 * After JDK5, the Lock interface can replace the synchronization keyword
 * The functionality is the same, but more flexible
 * */
public class Ticket implements Runnable {
	private int ticket = 100;
	//The interface cannot instantiate the object, just use the reference of the subclass
	private Lock l=new ReentrantLock();

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			l.lock();	
				if (ticket > 0) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace ();
					}
					System.out.println(Thread.currentThread().getName() + "sale" + (ticket--) + "ticket");
				}else{
					return;
				}
				l.unlock();
			}

		}
}
package com.oracle.demo03;

public class Test {
	public static void main(String[] args) {
		Ticket t = new Ticket();
		Thread t0 = new Thread(t);
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t0.start();
		t1.start();
		t2.start();
	}
}

deadlock

The premise of deadlock is that a thread must have the resources of two objects at the same time to execute the program.
1. Thread 1 first owns object 1, then tries to own object 2
2. Thread 2 first owns object 2, then tries to own object 1
3. Thread 1 waits for thread 2 to release object 2
4. At the same time, thread 2 waits for thread 1 to release Object 1
will. . . Keep waiting until the sky and the earth are old, the sea is dry and the rocks are rotten, the mountains have no edges, and the heaven and the earth are united. . .

 

package com.oracle.demo04;

public class LockA {
	private LockA () {

	}
    // Guarantee the uniqueness of A lock
	public final static LockA la = new LockA ();

}
package com.oracle.demo04;

public class LockB {
	private LockB() {

	}
    / / Guaranteed the uniqueness of B lock
	public final static LockB lb = new LockB();
}
package com.oracle.demo04;

public class DeadLock implements Runnable {
	private int i = 0;

	@Override
	public void run() {
		while (true) {
			if (i % 2 == 0) {
				synchronized (LockA.la) {
					System.out.println("if...LockA");
					synchronized (LockB.lb) {
						System.out.println("if...LockB");
					}
				}
			} else {
				synchronized (LockB.lb) {
					System.out.println("else...LockB");
					synchronized (LockA.la) {
						System.out.println("else...LockA");

					}
				}
			}
			i++;
		}

	}

}
package com.oracle.demo04;

public class Test {
	public static void main(String[] args) {
		DeadLock dl = new DeadLock();
		Thread t0 = new Thread(dl);
		Thread t1 = new Thread(dl);
		t0.start();
		t1.start();
	}
}

Wait for the wake-up mechanism

Communication between threads: Multiple threads are processing the same resource, but the processing actions (tasks of the threads) are different.

Waiting for the wake-up mechanism: Through certain means, each thread can effectively utilize resources, which is the waiting and wake-up mechanism

The methods involved in waiting for the wake-up mechanism:

wait(): Wait, release the execution qualification and execution right of the executing thread, and store it in the thread pool

notify(): wake up, wake up the threads in the thread pool that are wait(), wake up one at a time, and it is arbitrary

notifyAll(): wake up all, you can wake up all wait() threads in the thread pool

The so-called wake -up : is to make the thread in the thread pool qualified for execution . It must be noted that these methods are only valid in synchronization . At the same time, when these methods are used, they must indicate the lock they belong to , so that it can be clear which thread on which lock these methods operate.

These methods are all defined in the Object class , because when these methods are used, they must indicate the lock to which they belong, and the lock can be arbitrary, and the methods that can be called by any object must be defined in the Object class.

E.g:

The input thread enters name and sex into the Resource , and the output thread outputs from the resource. The first tasks to be completed are:

l 1. When the input finds that there is no data in the Resource, start the input, and after the input is completed, call the output to output. If there is data, wait();

l 2. When the output finds that there is no data in the Resource, it will wait(); when it finds that there is data, it will output, and then wake up the input to input the data.

package com.oracle.demo05;

public class Resouse {
    public  String name;
    public  String sex;
    public boolean flag=false;
}
//flag flag: when true, the assignment is complete
// When false, get the value complete
//Input class: true, wait, false, assignment, after assignment is completed, change flag to true notify output, wait() by yourself
//Output class: false, wait, true, value, after the value is completed, change the flag to false notify input, wait() by yourself

package com.oracle.demo05;

public class Input implements Runnable {
	private Resouse r;

	public Input(Resouse r) {
		this.r = r;
	}

	@Override
	public void run() {
		// Enter data into the resource object
		int i = 0;
		while (true) {
			//r indicates the uniqueness of the lock
			synchronized (r) {
				if (r.flag) {
					try {
						r.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace ();
					}
				}
				if (i % 2 == 0) {
					r.name = "Zhang San";
					r.sex = "女";
				} else {
					r.name = "lisi";
					r.sex = "nan";
				}
				r.flag = true;
				r.notify();
			}
			i++;
		}
	}

}

package com.oracle.demo05;

public class Output implements Runnable {
	private Resouse r;

	public Output(Resouse r) {
		this.r = r;
	}

	@Override
	public void run() {
		// output data from the resource object
		while (true) {
			synchronized (r) {
				if (!r.flag) {
					try {
						r.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace ();
					}
				}
				System.out.println(r.name + "..." + r.sex);
				r.flag = false;
				r.notify();
			}

		}
	}
}

package com.oracle.demo05;


public class Test {
	public static void main(String[] args) {
		Resouse r = new Resouse ();
		Input in = new Input(r);
		Output out = new Output(r);
		Thread tin = new Thread(in);
		Thread tout = new Thread(out);
		tin.start();
		all.start();
	}
}

  

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324878527&siteId=291194637